在散列数据库存储密码时,我总是使用正确的每个条目的盐字符串.根据我的需要,将盐存储在哈希密码旁边的数据库中一直运行正常.
但是,有些人建议将盐与数据库分开存储.他们的论点是,如果数据库受到攻击,攻击者仍然可以构建一个彩虹表,将一个特定的盐字符串考虑在内,以便一次破解一个帐户.如果此帐户具有管理员权限,那么他甚至可能不需要破解任何其他帐户.
从安全角度来看,将盐储存在不同的地方是否值得?考虑在同一台机器上具有服务器代码和DB的Web应用程序.如果盐存储在该机器上的平面文件中,则很可能如果数据库受到损害,则salt文件也是如此.
有什么建议的解决方案吗?
我在理解盐密封的目的时遇到了一些麻烦.据我所知,主要用途是阻碍彩虹表攻击.但是,我看到实现这一点的方法似乎并没有真正解决问题.
我见过许多教程,建议将盐用作以下内容:
$hash = md5($salt.$password)
Run Code Online (Sandbox Code Playgroud)
原因是哈希现在不映射到原始密码,而是密码和盐的组合.但是说$salt=foo和$password=bar和$hash=3858f62230ac3c915f300c664312c63f.现在有人用彩虹表可以反转哈希并提出输入"foobar".然后他们可以尝试所有密码组合(f,fo,foo,... oobar,obar,bar,ar,ar).获取密码可能需要几毫秒,但其他情况并不多.
我见过的其他用途是在我的linux系统上.在/ etc/shadow中,散列密码实际上与 salt一起存储.例如,"foo"的盐和"bar"的密码将散列到此:$1$foo$te5SBM.7C25fFDu6bIRbX1.如果一个黑客以某种方式能够得到这个文件,我不知道盐服务的目的是什么,因为te5SBM.7C25fFDu6bIRbX已知反向哈希包含"foo".
感谢任何人都可以解决这个问题.
编辑:谢谢你的帮助.为了总结我的理解,salt使得散列密码更加复杂,从而使得它更不可能存在于预先计算的彩虹表中.我之前误解的是,我假设所有哈希都存在彩虹表.
bCrypt的javadoc有如何加密密码的代码:
String pw_hash = BCrypt.hashpw(plain_password, BCrypt.gensalt());
Run Code Online (Sandbox Code Playgroud)
要检查明文密码是否与先前已经散列的密码匹配,请使用checkpw方法:
if (BCrypt.checkpw(candidate_password, stored_hash))
System.out.println("It matches");
else
System.out.println("It does not match");
Run Code Online (Sandbox Code Playgroud)
这些代码片段向我暗示随机生成的盐被丢弃.是这种情况,还是只是一个误导性的代码片段?
我刚刚浏览了DavidHayden关于哈希用户密码的文章之一.
真的,我无法得到他想要实现的目标.
这是他的代码:
private static string CreateSalt(int size)
{
//Generate a cryptographic random number.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] buff = new byte[size];
rng.GetBytes(buff);
// Return a Base64 string representation of the random number.
return Convert.ToBase64String(buff);
}
private static string CreatePasswordHash(string pwd, string salt)
{
string saltAndPwd = String.Concat(pwd, salt);
string hashedPwd =
FormsAuthentication.HashPasswordForStoringInConfigFile(
saltAndPwd, "sha1");
return hashedPwd;
}
Run Code Online (Sandbox Code Playgroud)
有没有其他C#方法来散列密码并添加盐?
这比普通MD5更安全吗?我刚刚开始研究密码安全性.我是PHP的新手.
$salt = 'csdnfgksdgojnmfnb';
$password = md5($salt.$_POST['password']);
$result = mysql_query("SELECT id FROM users
WHERE username = '".mysql_real_escape_string($_POST['username'])."'
AND password = '$password'");
if (mysql_num_rows($result) < 1) {
/* Access denied */
echo "The username or password you entered is incorrect.";
}
else {
$_SESSION['id'] = mysql_result($result, 0, 'id');
#header("Location: ./");
echo "Hello $_SESSION[id]!";
}
Run Code Online (Sandbox Code Playgroud) 我一直都很好奇...在使用散列密码进行散列时哪个更好:前缀或后缀?为什么?或者它是否重要,只要你加盐?
为了解释:我们所有(希望)现在我们应该知道盐之前,我们哈希它存储在数据库中的密码[ 编辑:所以你能避免类似的事情发生了什么杰夫阿特伍德最近.通常,这是通过在将盐传递给散列算法之前将盐与密码连接来完成的.但是这些例子各不相同......有些例子在密码之前加盐.一些示例在密码后添加salt .我甚至看到过一些尝试将盐放在中间的人.
那么哪种方法更好,为什么呢?有没有一种方法可以减少哈希冲突的可能性?我的谷歌搜索没有找到关于这个问题的体面分析.
编辑:很棒的答案人们!对不起,我只能选一个答案.:)
我遇到了一个讨论,其中我了解到我一直在做的事情实际上并没有腌制密码而是给它们加油,而且我已经开始使用以下功能:
hash_function($salt.hash_function($pepper.$password)) [multiple iterations]
Run Code Online (Sandbox Code Playgroud)
忽略所选的哈希算法(我希望这是对盐和辣椒的讨论,而不是特定的算法,但我使用的是安全算法),这是一个安全的选择还是我应该做一些不同的事情?对于那些不熟悉这些条款的人:
甲盐是通常存储与设计,使其不可能使用哈希表来破解密码的数据库中的字符串中的随机生成值.由于每个密码都有自己的盐,因此必须对它们进行单独的强制攻击才能破解它们; 但是,由于salt使用密码哈希存储在数据库中,因此数据库泄露意味着丢失两者.
甲胡椒是从中旨在是秘密的数据库(在应用程序的源代码通常硬编码)分开存储站点范围静态值.它的使用是为了破坏数据库不会导致整个应用程序的密码表变得暴力破解.
有什么我缺少的,并且正在腌制和密封我的密码是保护用户安全的最佳选择吗?这样做有没有潜在的安全漏洞?
注意:为了讨论的目的,假设应用程序和数据库存储在不同的机器上,不共享密码等,因此违反数据库服务器并不会自动意味着破坏应用程序服务器.
当盐析和散列用户密码时,任何盐显然都会有所帮助.盐有多长时间有什么最佳做法吗?我将盐存储在我的用户表中,所以我希望在存储大小和安全性之间进行最佳权衡.是一个随机的10个字符的盐吗?或者我需要更长的时间?
更新:请注意我不是在询问盐是什么,彩虹表是什么,字典攻击是什么,或盐的目的是什么.我在查询:如果你知道用户的salt和hash,那么计算密码是不是很容易?
我理解这个过程,并在我的一些项目中自己实现它.
s = random salt
storedPassword = sha1(password + s)
Run Code Online (Sandbox Code Playgroud)
在您存储的数据库中:
username | hashed_password | salt
Run Code Online (Sandbox Code Playgroud)
我所看到的盐析的每次实施都会在密码的末尾添加盐,或者开始:
hashed_Password = sha1(s + password )
hashed_Password = sha1(password + s)
Run Code Online (Sandbox Code Playgroud)
因此,来自黑客的字典攻击是值得他的盐(哈哈),只需针对上面列出的常见组合中存储的盐运行每个关键字.
当然,上述实现只是为黑客增加了另一个步骤,而没有真正解决潜在的问题?有什么替代方法可以解决这个问题,还是我误解了这个问题?
我唯一能想到的就是有一个秘密混合算法,它以随机模式将salt和密码绑定在一起,或者将其他用户字段添加到散列过程中,这意味着黑客必须能够访问数据库和代码才能获得花边他们为字典攻击证明富有成效.(更新,正如评论中指出的那样,最好假设黑客可以访问您的所有信息,因此这可能不是最好的).
让我举一个例子,说明我如何建议黑客用密码和哈希列表来破解用户数据库:
来自我们黑客数据库的数据:
RawPassword (not stored) | Hashed | Salt
--------------------------------------------------------
letmein WEFLS... WEFOJFOFO...
Run Code Online (Sandbox Code Playgroud)
通用密码字典:
Common Password
--------------
letmein
12345
...
Run Code Online (Sandbox Code Playgroud)
对于每个用户记录,循环公共密码并对其进行哈希:
for each user in hacked_DB
salt = users_salt
hashed_pw = users_hashed_password
for each common_password
testhash = sha1(common_password + salt)
if testhash = hashed_pw then
//Match! Users password …Run Code Online (Sandbox Code Playgroud) 这段代码应该用盐哈希密码.salt和哈希密码正在保存在数据库中.密码本身不是.
考虑到操作的敏感性,我想确保一切都是犹太洁食.
注意:我习惯使用url安全版的b64encode.
import hashlib
import base64
import uuid
password = 'test_password'
salt = base64.urlsafe_b64encode(uuid.uuid4().bytes)
t_sha = hashlib.sha512()
t_sha.update(password+salt)
hashed_password = base64.urlsafe_b64encode(t_sha.digest())
Run Code Online (Sandbox Code Playgroud) salt ×10
hash ×8
passwords ×6
security ×4
cryptography ×3
encryption ×2
bcrypt ×1
c# ×1
java ×1
php ×1
python ×1
rainbowtable ×1