关于php:openssl_digest vs hash vs hash_hmac? SALT和HMAC之间的区别?

openssl_digest vs hash vs hash_hmac? Difference between SALT & HMAC?

我想使用SHA512来存储密码。 为此,应该使用openssl_digesthashhash_hmac中的哪一个,为什么?

SALTHMAC有什么区别?

我刚刚读到HMAC建立在哈希函数之上。

那么SHA512+SALT+HMAC确实是必需的还是SHA512+SALTSHA512+HMAC


因此,首先,让我们澄清一件事。 openssl_digest() === hash()。它只是另一个功能不同而功能完全相同的功能。它计算输入的加密哈希。

因此,现在我们有一个问题:在存储密码时,哪个更好:hashhash_hmac

简短答案:

都没有

长答案:

事实证明,彩虹桌已经死了。仅使用hash($password . $salt)甚至hash_hmac($password, $salt)不足以存储密码。期。如果这样做,请立即停止。

原因很简单:计算机(或GPU)上的计算时间非常便宜。它是如此便宜,以至于暴力破解密码列表已经足够便宜,您需要担心它。请记住,哈希函数的设计速度很快。不贵啊...

但是,事实证明,有一种方法可以使这些快速哈希函数变得更昂贵。实际上,这很简单:迭代。

现在,我知道您在想什么。您将仅遍历哈希:

1
2
3
4
5
6
function hash_password($password, $salt) {
    $hash = hash("sha512", $password . $salt);
    for ($i = 0; $i < 1000; $i++) {
        $hash = hash("sha512", $hash);
    }
}

当然足够了吧?不。正如"散列和加密之间的根本区别"所述,这不是一个好主意。那么,为什么不只反馈密码并再次输入密码呢?

1
2
3
4
5
6
function hash_password($password, $salt) {
    $hash = hash("md5", $salt . $password);
    for ($i = 0; $i < 1000; $i++) {
        $hash = hash("md5", $hash . $password);
    }
}

实际上,这正是PHPASS所使用的(稍作调整,但这是基本算法)...

因此,现在对hash_password的1次调用将执行1000个哈希周期。

但是,我们可以对此进行改进吗?

好吧,事实证明,我们可以。下一步要做的逻辑是看是否可以在相同的时间内获得更多的哈希周期。这就是hash_hmac()出现的地方。事实证明,HMAC每次调用时都使用2个哈希周期。而且由于全部为C,因此只花费hash()进行单轮操作所需时间的1.5倍。

因此,这意味着如果将hash替换为hash_hmac,我们可以立即看到在指定时间内完成的工作量增加了33%。所以现在我们在这里:

1
2
3
4
5
6
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,这是一种自适应哈希算法。与上面的算法相比,它具有使用更多内存的优点(大约4到5kb)。因此,它更耐并行化。而且它抗蛮力,因为它在计算上很昂贵。

幸运的是,它可用于PHP:

1
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。但是不要仅仅因为不想拉依赖关系而发明自己的东西……那只是疏忽。

更多阅读:

  • 正确加盐密码-反对胡椒案
  • GPU加速PBKDF2
  • 很多哈希迭代,每次都要添加盐吗?
  • MD5解码,他们如何做


HMAC是使用哈希算法(如SHA512)的一种特定方式。它用于对邮件进行签名,然后您可以验证该邮件来自特定的签名者,并且没有被更改。所以这不是您想要的。

盐用于为应加密或散列的文本添加一些"随机性"。关键是,即使您多次加密相同的文本,您也会得到不同的结果。这使得进行一些攻击变得更加困难。这就是您想要的:SHA512(salt+password)

对于存储密码,我能想到的最安全的方法是:

(免责声明:我对密码学不是很有经验,可能会有更好的解决方案)

  • 客户端(JavaScript代码?)将生成一个盐值。
  • 然后,客户端将salt和密码结合在一起,并通过您的哈希算法运行结果。
  • 然后,客户端将盐和哈希值都传输到存储它的服务器(最好在不同的位置)。

要验证密码,您需要执行以下操作:

  • 将盐传递给客户。
  • 客户端结合盐和输入的密码,通过您的哈希算法运行它。
  • 客户端将哈希值发送到服务器。
  • 服务器将哈希值与存储的哈希值进行比较。如果它们匹配,则使用相同的密码。

当然,您可以以明文形式传输密码,并在服务器上进行整个加盐和哈希处理,但这会大大削弱您的解决方案。永远不要以明文形式传输密码。

但是"将盐传递给客户"部分可能是一个问题。我可以想象解决此问题的一种方法是以某种方式从用户名中导出盐(最简单的方法:简单地执行lowercase(username) + password),但是这样做的问题是盐是可预测的,因此会稍微削弱您的解决方案一点。但是,它仍然比传输"原始"哈希更好,并且您甚至不需要存储盐,因为每次都可以从用户名中获取盐。如果您的密码数据库被盗了,它仍然可以通过这种"用用户名称呼"方法来抵抗彩虹表攻击。

问题在于中间人攻击仍然是可能的。如果攻击者拦截用户名并进行哈希处理,则它具有所有相关信息,并且与传输纯文本密码没有什么不同。因此,您可能希望使用SSL(HTTPS)保护连接。


据IT安全专家介绍:

使用Bcrypt来源:https://security.stackexchange.com/a/10905/7599。

我会根据SO的观点给出答案。

1
openssl_digest vs hash vs hash_hmac
  • openssl_digest-计算摘要。
  • hash生成哈希值(消息摘要)
  • hash_hmac —使用HMAC方法生成键控哈希值
  • 并且,在密码学中,基于散列的消息认证码(HMAC)是用于计算包含密码散列函数和密钥的消息认证码(MAC)的特定结构。

    正如ircmaxell所说,hashhash_hmac对于使用SHA-512存储密码并不更好。我宁愿说,您可以使用openssl_digest来存储密码。

    查看PHP的SHA-512库

    1
    SALT vs HMAC
  • 在这种情况下,哈希是一种单向函数-即使从参数(密码)中查找结果非常容易,但很难(或不可能)找到产生给定结果的任何参数的函数。
  • 盐是一些辅助数据,可将参数扩展为哈希函数。这很有用,因为它通过观察两个散列密码具有相同的值来防止意外发现密码。对于盐,只有盐和密码都匹配时,存储/传输的值才会相同。
  • HMAC指的是将哈希(和可选的盐)应用于"消息认证代码"-根据上下文可能是密码...或者至少没有什么阻止您将密码传递给HMAC的,如果是消息验证码。
  • HMAC旨在用于您有随机和秘密的情况
    键。对于这些情况,HMAC通常优于其他方式
    将密钥合并到哈希函数中。 (例如,使用HMAC
    负责扩展攻击等)

    盐通常是一个不是秘密的随机值。也就是说,什么时候
    您通常使用"盐"一词指的是
    攻击者可能非常了解的随机值。安全
    因此,系统的功能不应取决于所保留的盐
    秘密。在这些情况下,HMAC通常不是一个很好的选择。

    HMAC和Salt的比较是不合逻辑的。我个人会使用盐和哈希函数...而且我不会对哈希函数的强度抱有偏执,因为它不可能是任何实际系统中的薄弱环节...。

    参见http://www.derkeiler.com/Newsgroups/sci.crypt/2006-01/msg00321.html