产生随机“位点盐”的好方法是什么?用于创建密码检索令牌?

发布于 2024-09-10 07:33:24 字数 984 浏览 1 评论 0原文

我想创建一个站点范围的哈希,在创建密码检索令牌时用作盐。我一直在 stackoverflow 上徘徊,试图了解做到这一点的最佳方法。

重置过程如下:

当用户请求密码重置电子邮件时,代码会生成检索令牌:

$token = hash_hmac('sha256', $reset_hash* , $site_hash)

*$reset_hash 是使用 phpass HashPassword() 函数创建的哈希值,保存在用户表中。

然后,我将 URL 中的令牌发送到用户的电子邮件地址。他们在令牌在一小时内超时之前单击。我将他们的提交与服务器端生成的挑战令牌进行匹配。如果匹配,则他们被迫选择新密码,然后登录。

我想知道生成 $site_key 的最佳方法。我正在考虑使用另一个由随机数播种的 HMAC 哈希值:

$site_key = hash_hmac('sha256', MCRYPT_DEV_RANDOM, MCRYPT_DEV_RANDOM);

这会产生如下内容:

98bb403abbe62f5552f03494126a732c3be69b41401673b08cbfefa46d9e8999

这是否是用于此目的的适当随机数?我是否使这个问题过于复杂化,或者以错误的方式处理它?

这个答案启发我使用 HMAC

<强>编辑:我试图避免一些同事催促的“秘密问题”步骤,因此我希望重置链接提供重置密码的单个步骤。因此,我担心这个过程是否足够安全以保护包含敏感信息的系统。

目前已解决:我将使用 The Rook 所描述的随机数作为重置令牌。感谢大家的评论和反馈。

I would like to create a site-wide hash to be used as salt in creating password retrieval tokens. I have been bouncing around stackoverflow trying to get a sense of the best way to do this.

Here's the reset process:

When a user requests a password reset email the code generates a retrieval token:

$token = hash_hmac('sha256', $reset_hash* , $site_hash)

*$reset_hash is a hash created using phpass HashPassword() function, saved in the user table.

I then send the token in a URL to the users email address. They click before the token times out in an hour. I match their submission with the a challenge token generated server-side. If it matches, then they are forced to choose a new password, and then login.

I would like to know the best way to generate the $site_key. I am thinking of using another HMAC hash that is seeded by random numbers:

$site_key = hash_hmac('sha256', MCRYPT_DEV_RANDOM, MCRYPT_DEV_RANDOM);

This produces something like this:

98bb403abbe62f5552f03494126a732c3be69b41401673b08cbfefa46d9e8999

Will this be a suitably random to be used for this purpose? Am I overcomplicating this, or approaching it the wrong way?

I was inspired to use HMAC by this answer

EDIT: I am trying to avoid a 'secret question' step urged by some of my coworkers, so I would like the reset link to provide a single step to resetting the password. Therefore, my concern is that this process be secure enough to safeguard a system containing sensitive information.

RESOLVED, for now: I am going to go with a nonce as described by The Rook as the reset token. Thanks everyone for the comments and feedback.

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

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

发布评论

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

评论(1

甩你一脸翔 2024-09-17 07:33:24

首先,你不是在谈论盐。您正在谈论加密随机数,当您对密码加盐时,您应该使用加密随机数。在重置密码的情况下,它应该是存储在数据库中的随机数。具有“位点盐”并不是有利的。

首先,我不喜欢 uniqid()因为这是一个时间繁重的计算,并且时间是一个非常弱的种子rand() 与 mt_rand(),剧透:rand() 完全是垃圾。

在 Web 应用程序中,安全秘密的良好来源是对熵池(例如 /dev/urandom)的非阻塞访问。从 PHP 5.3 开始,PHP 应用程序可以使用 openssl_random_pseudo_bytes(),Openssl 库将根据您的操作系统选择最佳的熵源,在 Linux 下这意味着应用程序将使用 /dev/ urandom。 Scott 的这个代码片段相当不错

function crypto_rand_secure($min, $max) {
        $range = $max - $min;
        if ($range < 0) return $min; // not so random...
        $log = log($range, 2);
        $bytes = (int) ($log / 8) + 1; // length in bytes
        $bits = (int) $log + 1; // length in bits
        $filter = (int) (1 << $bits) - 1; // set all lower bits to 1
        do {
            $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
            $rnd = $rnd & $filter; // discard irrelevant bits
        } while ($rnd >= $range);
        return $min + $rnd;
}

function getToken($length=32){
    $token = "";
    $codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    $codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
    $codeAlphabet.= "0123456789";
    for($i=0;$i<$length;$i++){
        $token .= $codeAlphabet[crypto_rand_secure(0,strlen($codeAlphabet))];
    }
    return $token;
}

To start with, your not talking about a salt. You're talking about a Cryptographic Nonce, and when you salt a password you should use a Cryptographic Nonce. In the case of resetting passwords, it should be a random number that is stored in the database. It is not advantageous to have have a "site salt".

First and foremost I don't like uniqid() because it's a time heavy calculation and time is a very weak seed. rand() vs mt_rand(), spoiler: rand() is total crap.

In a web application a good source for secure secrets is non-blocking access to an entropy pool such as /dev/urandom. As of PHP 5.3, PHP applications can use openssl_random_pseudo_bytes(), and the Openssl library will choose the best entropy source based on your operating system, under Linux this means the application will use /dev/urandom. This code snip from Scott is pretty good:

function crypto_rand_secure($min, $max) {
        $range = $max - $min;
        if ($range < 0) return $min; // not so random...
        $log = log($range, 2);
        $bytes = (int) ($log / 8) + 1; // length in bytes
        $bits = (int) $log + 1; // length in bits
        $filter = (int) (1 << $bits) - 1; // set all lower bits to 1
        do {
            $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
            $rnd = $rnd & $filter; // discard irrelevant bits
        } while ($rnd >= $range);
        return $min + $rnd;
}

function getToken($length=32){
    $token = "";
    $codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    $codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
    $codeAlphabet.= "0123456789";
    for($i=0;$i<$length;$i++){
        $token .= $codeAlphabet[crypto_rand_secure(0,strlen($codeAlphabet))];
    }
    return $token;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文