我想使用SHA512来存储密码。要做到这一点,我应该使用openssl_digest
,hash
和hash_hmac
中的哪一个?为什么?
SALT
&之间有什么区别? HMAC
?
我刚刚读到HMAC是建立在哈希函数之上的。
SHA512+SALT+HMAC
真的有必要还是SHA512+SALT
或SHA512+HMAC
?
答案 0 :(得分:57)
所以,首先,让我们清楚一件事。 openssl_digest()
=== hash()
。它只是另一个不同名称的功能,完全相同。它计算输入的加密哈希值。
所以,现在我们有了一个问题:存储密码时,哪个更好:hash
或hash_hmac
?
无论
事实证明,The Rainbow Table Is Dead。仅使用hash($password . $salt)
甚至hash_hmac($password, $salt)
对于密码存储来说还不够好。期。如果您这样做,请立即停止。
原因很简单:计算机(或GPU)上的计算时间非常便宜。这是如此便宜,以至于蛮力的密码列表足够便宜,你需要担心它。请记住,哈希函数设计为 fast 。不贵...
但是,事实证明,有一种方法可以使这些快速哈希函数更加昂贵。事实上,它非常简单:迭代。
现在,我知道你在想什么。你只是循环遍历哈希:
function hash_password($password, $salt) {
$hash = hash("sha512", $password . $salt);
for ($i = 0; $i < 1000; $i++) {
$hash = hash("sha512", $hash);
}
}
当然这很好,对吧?不。正如Fundamental Difference Between Hashing and Encryption中所解释的那样,这不是一个好主意。那么为什么不再重新输入密码和盐?
function hash_password($password, $salt) {
$hash = hash("md5", $salt . $password);
for ($i = 0; $i < 1000; $i++) {
$hash = hash("md5", $hash . $password);
}
}
事实上,这正是PHPASS使用的(略微调整,但这是基本算法)......
所以现在1次调用hash_password
执行1000个哈希循环。
但我们可以改进吗?
嗯,事实证明,我们可以。下一个合乎逻辑的做法是看看我们是否可以在相同的时间内获得更多的哈希循环。这就是hash_hmac()
的用武之地。事实证明,HMAC
每次调用时都会使用2个哈希周期。而且因为它全部都是C,所以它只花费hash()
进行一轮所需时间的1.5倍。
这意味着如果我们将hash
替换为hash_hmac
,我们可以立即看到在指定时间内完成的工作量增加了33%。所以现在我们在这里:
function hash_password($password, $salt) {
$hash = hash_hmac("md5", $salt, $password);
for ($i = 0; $i < 1000; $i++) {
$hash = hash_hmac("md5", $hash, $password);
}
}
这实际上是PBKDF2的基本内循环。
但我们可以变得更好吗?
是的,再次,我们可以变得更好。如果我们仔细观察,我们可以看到 - 除了密码和盐 - 所有上述算法都使用非常少量的内存。在sha512的情况下,它们将使用128到256字节(缓冲区和状态)的顺序来散列密码。由于内存使用量非常小,因此在GPU中并排运行大量内存非常简单。如果我们只能增加内存使用量......
嗯,事实证明,我们可以简单地使用bcrypt
,这是一种自适应散列算法。它的优点是它使用 more 内存而不是上述算法(大约4到5kb)。因此,对并行化更具抵抗力。而且由于它的计算成本很高,因此它对强制执行是不利的。
幸运的是,它适用于PHP:
crypt($password, '$2y$07$usesomesillystringforsalt$')
请注意,crypt()
使用了许多算法,但$2y$
和$2a$
算法为bcrypt
。
但我们可以改进吗?
类-的。有一种名为scrypt的相对较新的算法。它比bcrypt更好,因为它的计算成本非常高,但是使用了更多的内存(大约20mb到40mb来散列单个密码)。因此,它对并行化更具抵抗力......
不幸的是,scrypt
在PHP 尚未中不可用(我正在努力改变它)。在此之前,请使用bcrypt
...
在最近的LinkedIn,LastFM,Hotmail,Gawker等课程之后,证据显示很多的人做错了。不要做错,使用带有审查算法的库。使用CRYPT_BLOWFISH
(bcrypt),使用PHPASS,使用PasswordLib。但是,不要仅仅因为你不想引起依赖而发明自己的......这只是疏忽。
更多阅读:
答案 1 :(得分:7)
HMAC是使用哈希算法(如SHA512)的特定方法。它用于签署消息,然后您可以验证消息是否来自特定签名者并且未被更改。所以这不是你想要的。
salt用于向应加密或散列的文本添加一些“随机性”。关键是,即使您多次加密相同的文本,您也会得到不同的结果。这使得进行一些攻击变得更加困难。 是您想要的:SHA512(salt+password)
。
对于存储密码,我能想象的最安全的方式是:
(免责声明:我对加密技术不是很熟悉,而且可能有更好的解决方案)
要验证密码,您可以执行以下操作:
当然,你可以用明文传输密码并在服务器上进行整个salting和散列,但这会大大削弱你的解决方案。您应该从不以明文传输密码。
但是“将盐传递给客户端”部分可能是个问题。我可以想象解决这个问题的一种方法是以某种方式从用户名中获取salt(最简单的方法:只做lowercase(username) + password
),但问题是盐是可预测的,从而削弱你的解决方案一点点。然而,它仍然方式比传输“原始”哈希更好,你甚至不需要存储盐,因为你每次都可以从用户名中获取它。如果您的密码数据库被盗,它仍然可以通过这种“用户名腌制”方法抵御彩虹表攻击。
问题在于仍然可以进行中间人攻击。如果攻击者拦截用户名和哈希,则它具有所有相关的信息,并且与发送明文密码没有任何不同。因此,您可能希望使用SSL(HTTPS)保护连接。
答案 2 :(得分:3)
根据IT安全专家的说法:
使用Bcrypt来源:https://security.stackexchange.com/a/10905/7599。
我会根据SO的观点给出答案。
openssl_digest vs hash vs hash_hmac
在密码学中,a hash-based message authentication code (HMAC)是用于计算包含加密散列函数和密钥的消息验证代码(MAC)的特定结构。
正如ircmaxell所说,hash
或hash_hmac
不适合使用SHA-512存储密码。我宁愿说,您可以使用openssl_digest
来存储密码。
SALT vs HMAC
HMAC旨在用于您有随机和秘密的情况 键。对于这些情况,HMAC通常比其他方式更好 将密钥合并到散列函数中。 (例如,使用HMAC 负责扩展攻击等事情。)
盐通常是一个非秘密的随机值。也就是说,什么时候 你使用术语盐,你通常指的是有一个 攻击者可能已经知道的随机值。安全 因此,系统应该不依赖于保存的盐 秘密。在这些情况下,HMAC通常不是一个很好的选择。
HMAC和Salt比较不合逻辑。就个人而言,我会使用一个盐和一个哈希函数......我不会对哈希函数的强弱感到偏执,因为它不太可能成为任何实际系统中的薄弱环节....
请参阅http://www.derkeiler.com/Newsgroups/sci.crypt/2006-01/msg00321.html