PHP 密码存储与 HMAC+nonce - 随机数随机性重要吗?

发布于 2024-10-10 16:48:13 字数 600 浏览 3 评论 0原文

几年来,我在 stackoverflow 上询问如何确保 PHP 密码存储安全。 主要答案建议使用以下哈希算法:

function hash_password($password, $nonce) {
  global $site_key;
  return hash_hmac('sha512', $password . $nonce, $site_key);
}

答案建议使用随机随机数。与简单的唯一随机数相比,使用随机随机数有什么优势吗?

例如,每个用户可以有自己的 ID,该 ID 不会改变。然而,我们假设用户 ID 是连续的(使用 MySQL 的自动增量功能构建),因此不是随机的。用户 ID 是一个好的随机数还是随机性很重要?

现在,每个用户都可以选择一个用户名。每个用户都有自己的用户名,并且不会改变,两个不同的用户不能有相同的用户名。 用户名仍然不是随机的,但也不是连续的。用户名作为随机数是否足够好?这会比使用用户 ID 更好吗?

A few years I asked here on stackoverflow about how to make PHP password storage safe.
The main answer suggests using the following hashing algorithm:

function hash_password($password, $nonce) {
  global $site_key;
  return hash_hmac('sha512', $password . $nonce, $site_key);
}

The answer suggests using a random nonce. Is there any advantage in having a random nonce over simple unique nonces?

For instance, each user can have its own ID which does not change. However, let's assume user IDs are sequential(built with MySQL's auto increment feature) and therefore not random. Would the user ID be a good nonce or is randomness important?

Now, each user can pick an username. Each user has its own username which does not change, and two different users can't have the same username.
Usernames are still not random, but they aren't sequential either. Would usernames be good enough as a nonce? Would it be better than using the user ID?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

无法言说的痛 2024-10-17 16:48:13

这都是基于随机数是盐的假设......

如果随机数是指盐,那么是的,这需要制作更多的彩虹表。通常,一次加盐超过 20 个字符就足够了,但对于极端的安全条件,您可能需要为每个密码使用一个新的随机加盐。

在慢速哈希中也是不错的选择 http://www.php.net/ Manual/en/function.hash.php#89574,没有讽刺。但我喜欢成熟的。

没看到你回复的下半部分。详细说明:随机数用于防止使用彩虹表。 ID 是否有效仅取决于 ID 的长度。随机性在技术上并不重要,但只是需要更多的彩虹表。一个例子是,假设您使用字符“a”作为随机数,并且密码有 2 个字符长,则必须创建 a-aa、a-ab a-ac 等彩虹表。如果您每次都使用随机字符,则可能必须完成“a”的所有排列+其他随机字符的所有排列。

但一般来说制作彩虹桌需要相当长的时间。因此,如果你想出一种很长的盐,那么它很可能是彩虹表,因为它不存在。

THIS IS ALL ON THE ASSUMPTION THAT A NONCE IS A SALT...

If by nonce you mean a salt then yes that requires more rainbow tables to be made. Usually once salt over 20 characters suffices, but for extreme security conditions you would want a new random salt for each password.

Also good choice in a slow hash http://www.php.net/manual/en/function.hash.php#89574, no sarcasm. But I like ripemd.

Didnt see the bottom half of your response. To elaborate: Nonces are used to prevent the use of rainbow tables. Whether the ID's would work depends merely on the length of the IDs. Randomness is not technically important, but just makes more rainbow tables required. An example would be, lets say you used a character "a" as a nonce and the password were 2 characters long, a rainbow table of a-aa, a-ab a-ac and so on would have to be created. If you use a random one each time maybe all the permutations of 'a' would have to be done + all the permuatations of the other random characters.

But in general making rainbow tables take quite a long time. So if you come up with a salt thats long its likely the rainbow table for it doesnt exists.

失而复得 2024-10-17 16:48:13

我发现网上有一个关于这个主题的相当不错的教程。我不太记得在谷歌上我在哪里找到它,但让我看看我是否可以自己分解这个函数,因为它就在我面前......

首先是函数,它可以创建任何大小的密钥长度。我冒昧地对它进行了相当多的评论...

function pbkdf2($password,$salt,$iter_count = 1500,$key_length = 32,$algorithm = 'sha512') 
{
    /*
      @param string password -- password to be encrypted
      @param string salt -- salt to encrypt with
      @param int iter_count -- number of times to iterate blocks
      @param key_length -- length of key to return
      @param $algorithm -- algorithm to use in hashing

      @return string key
    */

    //determine the length of the hahs
    $hash_length = strlen(hash($algorithm,NULL,TRUE));
    //determine the number of key blocks to compute
    $key_blocks = ceil($key_length/$hash_length);
    //initialize key
    $key = '';

    //create the key itself
    //create blocks
    for($block_count = 1;$block_count <= $key_blocks;$block_count++)
    {
        //initalize hash for this block
        $iterated_block = $block = hash_hmac($algorithm,$salt.pack('N',$block_count),$password,TRUE);
        //iterate blocks
        for($iterate = 1;$iterate <= $iter_count;$iterate++)
        {
            //xor each iterate
            $iterated_block ^= ($block = hash_hmac($algorithm,$block,$password,TRUE));
        }
        //append iterated block
        $key .= $iterated_block;
    }
    //return the key
    return substr($key,0,$key_length);
}
  1. 它所做的第一件事就是计算出哈希值的长度。
  2. 接下来,它确定指定的密钥长度需要多少个密钥块
  3. 然后,它初始化要返回的哈希(密钥)
  4. 设置将创建每个块的 for 循环 获取
  5. 块的初始哈希,并将二进制块计数器附加到salt
  6. 开始循环迭代块 $iter_count 次(创建自身的哈希)
  7. XOR 每次迭代并将其附加到 $iterated_block (将前一个哈希与当前哈希进行异或)
  8. XOR 循环完成
  9. 将 $iterated_block 附加到每个块的 $key 块
  10. 循环完成
  11. 返回关键

我觉得这可能是最好的方法。也许我太偏执了?

I found that there was a fairly nice tutorial written online about this topic. I don't quite remember where on google I found it but let me see if I can break the function down well enough myself as it is right in front of me...

First the function, it can create a key length of any size. I took the liberty of commenting it fairly heavily...

function pbkdf2($password,$salt,$iter_count = 1500,$key_length = 32,$algorithm = 'sha512') 
{
    /*
      @param string password -- password to be encrypted
      @param string salt -- salt to encrypt with
      @param int iter_count -- number of times to iterate blocks
      @param key_length -- length of key to return
      @param $algorithm -- algorithm to use in hashing

      @return string key
    */

    //determine the length of the hahs
    $hash_length = strlen(hash($algorithm,NULL,TRUE));
    //determine the number of key blocks to compute
    $key_blocks = ceil($key_length/$hash_length);
    //initialize key
    $key = '';

    //create the key itself
    //create blocks
    for($block_count = 1;$block_count <= $key_blocks;$block_count++)
    {
        //initalize hash for this block
        $iterated_block = $block = hash_hmac($algorithm,$salt.pack('N',$block_count),$password,TRUE);
        //iterate blocks
        for($iterate = 1;$iterate <= $iter_count;$iterate++)
        {
            //xor each iterate
            $iterated_block ^= ($block = hash_hmac($algorithm,$block,$password,TRUE));
        }
        //append iterated block
        $key .= $iterated_block;
    }
    //return the key
    return substr($key,0,$key_length);
}
  1. First thing it does is figure out the length of the hash.
  2. Next it determines how many key blocks are required for the key length specified
  3. Then it initializes the hash (key) to return
  4. sets up the for loop that will create each block
  5. takes the initial hash of the block with the block counter in binary appended to the salt
  6. begins the loop to iterate the block $iter_count times (create a hash of itself)
  7. XOR each iterate and append it to $iterated_block (xor previous hash to current)
  8. XOR loop finishes
  9. append $iterated_block to $key for each block
  10. block loop finishes
  11. return the key

I feel this is probably the best way to do this. Maybe I am too paranoid?

握住你手 2024-10-17 16:48:13

为了存储足以使用的密码:

sha512(salt + password)

salt 对于每个用户来说应该是随机且唯一的。随机盐将使预先计算的哈希表攻击变得不可能:每个用户都需要自己计算的哈希表。如果您不使用随机盐,那么预先计算的表存在的机会会更高。

将盐放在密码之前将有助于隐藏哈希模式,以防某些用户具有相同的密码。

不需要Nonce,因为它是为了防止回复攻击。这种保护在您的架构中是不可能的。

使用HMAC来防止冲突是没有用的,因为a)我们使用散列而不是MAC,b)使SHA-512的冲突概率为50%您需要计算大约 2^256 个值。而2^256确实是一个天文数字。

For storing password enough to use:

sha512(salt + password)

salt should be random and unique for each user. Random salt will make precalculated hash tables attack impossible: each user will require his own calculated hash tables. If you'll use not random salt, then chance that precalculated table exists will be higher.

Position salt before password will help to hide hash patterns in case some users have same password.

Nonce is not needed, because it is for prevention a reply attack. This protection is not possible in your architecture.

Using HMAC to prevent collisions is useless, because a) we use hash not for MAC, b) to make probability of collision 50% for SHA-512 you need to calculate about 2^256 values. And 2^256 is truly astronomical number.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文