openssl_digest vs hash vs hash_hmac? SALT与...之间的区别HMAC?

时间:2012-01-21 12:01:50

标签: php security passwords hash

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


SALT&之间有什么区别? HMAC


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

SHA512+SALT+HMAC真的有必要还是SHA512+SALTSHA512+HMAC

3 个答案:

答案 0 :(得分:57)

所以,首先,让我们清楚一件事。 openssl_digest() === hash()。它只是另一个不同名称的功能,完全相同。它计算输入的加密哈希值。

所以,现在我们有了一个问题:存储密码时,哪个更好:hashhash_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 ...

旁注

在最近的LinkedInLastFMHotmailGawker等课程之后,证据显示很多的人做错了。不要做错,使用带有审查算法的库。使用CRYPT_BLOWFISH(bcrypt),使用PHPASS,使用PasswordLib。但是,不要仅仅因为你不想引起依赖而发明自己的......这只是疏忽。

更多阅读:

答案 1 :(得分:7)

HMAC使用哈希算法(如SHA512)的特定方法。它用于签署消息,然后您可以验证消息是否来自特定签名者并且未被更改。所以这不是你想要的。

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

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

(免责声明:我对加密技术不是很熟悉,而且可能有更好的解决方案)

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

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

  • 将盐传递给客户。
  • 客户端将salt和输入的密码组合在一起,通过散列算法运行它。
  • 客户端将哈希值发送给服务器。
  • 服务器将哈希值与存储的哈希值进行比较。如果匹配,则密码相同。

当然,你可以用明文传输密码并在服务器上进行整个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
  1. openssl_digest - 计算摘要。
  2. hash生成哈希值(消息摘要)
  3. hash_hmac - 使用HMAC方法生成键控哈希值
  4. 在密码学中,a hash-based message authentication code (HMAC)是用于计算包含加密散列函数和密钥的消息验证代码(MAC)的特定结构。

    正如ircmaxell所说,hashhash_hmac不适合使用SHA-512存储密码。我宁愿说,您可以使用openssl_digest来存储密码。

    请参阅SHA-512 library for PHP

    SALT vs HMAC
    
    1. 在此上下文中,哈希是一个one-way function - 即一个函数,它可以很容易地从参数(密码)中找到结果,但很难(或不可能)找到生成结果。
    2. salt是一些辅助数据,用于扩充哈希函数的参数。这很有用,因为它可以通过观察两个散列密码具有相同的值来防止意外发现密码。使用salt时,如果salt和密码都匹配,则存储/传输的值将相同。
    3. HMAC是指哈希(和可选盐)应用于“消息身份验证代码” - 根据上下文可能是密码...或者,至少,没有什么可以阻止你将密码传递给HMAC,就像它是消息验证码一样。
    4. HMAC旨在用于您有随机和秘密的情况 键。对于这些情况,HMAC通常比其他方式更好 将密钥合并到散列函数中。 (例如,使用HMAC 负责扩展攻击等事情。)

      盐通常是一个非秘密的随机值。也就是说,什么时候 你使用术语盐,你通常指的是有一个 攻击者可能已经知道的随机值。安全 因此,系统应该不依赖于保存的盐 秘密。在这些情况下,HMAC通常不是一个很好的选择。

      HMAC和Salt比较不合逻辑。就个人而言,我会使用一个盐和一个哈希函数......我不会对哈希函数的强弱感到偏执,因为它不太可能成为任何实际系统中的薄弱环节....

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