php md5(uniqid) 对随机唯一令牌有意义吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2593807/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 07:03:04  来源:igfitidea点击:

md5(uniqid) makes sense for random unique tokens?

phpsecurityhashrandompasswords

提问by Exception e

I want to create a token generator that generates tokens that cannot be guessed by the user and that are still unique (to be used for password resets and confirmation codes).

我想创建一个令牌生成器,它生成用户无法猜测的令牌,并且仍然是唯一的(用于密码重置和确认代码)。

I often see this code; does it make sense?

我经常看到这段代码;是否有意义?

md5(uniqid(rand(), true));

According to a commentuniqid($prefix, $moreEntopy = true)yields

根据评论uniqid($prefix, $moreEntopy = true)收益

first 8 hex chars = Unixtime, last 5 hex chars = microseconds.

前 8 个十六进制字符 = Unixtime,最后 5 个十六进制字符 = 微秒。

I don't know how the $prefix-parameter is handled..

我不知道 -$prefix参数是如何处理的..

So if you don't set the $moreEntopy flag to true, it gives a predictable outcome.

因此,如果您不将 $moreEntopy 标志设置为 true,它会给出可预测的结果。



QUESTION:But if we use uniqidwith $moreEntopy, what does hashing it with md5 buy us? Is it better than:

问题:但是如果我们使用uniqidwith $moreEntopy,用 md5 散列它会给我们带来什么?是否优于:

md5(mt_rand())

edit1:I will store this token in an database column with a unique index, so I will detect columns. Might be of interest/

编辑 1:我会将此令牌存储在具有唯一索引的数据库列中,因此我将检测列。可能有兴趣/

回答by rook

rand() is a security hazard and should never be used to generate a security token: rand() vs mt_rand()(Look at the "static" like images). But neither of these methods of generating random numbers is cryptographically secure. To generate secure secerts an application will needs to access a CSPRNGprovided by the platform, operating system or hardware module.

rand() 是一个安全隐患,永远不应该用于生成安全令牌:rand() 与 mt_rand()(看看“静态”像图像)。但是这些生成随机数的方法都不是密码安全的。为了生成安全的secerts,应用程序需要访问由平台、操作系统或硬件模块提供的CSPRNG

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:

在 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;
}

回答by Scott

This is a copy of another question I found that was asked a few months before this one. Here is a link to the question and my answer: https://stackoverflow.com/a/13733588/1698153.

这是我发现的另一个问题的副本,该问题是在这个问题之前几个月被问到的。这是问题和我的答案的链接:https: //stackoverflow.com/a/13733588/1698153

I do not agree with the accepted answer. According to PHPs own website "[uniqid] does not generate cryptographically secure tokens, in fact without being passed any additional parameters the return value is little different from microtime(). If you need to generate cryptographically secure tokens use openssl_random_pseudo_bytes()."

我不同意接受的答案。根据PHPs自己的网站"[uniqid] does not generate cryptographically secure tokens, in fact without being passed any additional parameters the return value is little different from microtime(). If you need to generate cryptographically secure tokens use openssl_random_pseudo_bytes()."

I do not think the answer could be clearer than this, uniqidis not secure.

我不认为答案会比这更清楚,uniqid是不安全的。

回答by Jarek Jakubowski

I know the question is old, but it shows up in Google, so...

我知道这个问题很老,但它出现在谷歌中,所以......

As others said, rand(), mt_rand()or uniqid()will not guarantee you uniqueness... even openssl_random_pseudo_bytes()should not be used, since it uses deprecated features of OpenSSL.

正如有人说,rand()mt_rand()uniqid()将不能保证您独特性......甚至openssl_random_pseudo_bytes()不应该被使用,因为它使用了过时的OpenSSL功能

What you should use to generate random hash (same as md5) is random_bytes()(introduced in PHP7). To generate hash with same length as MD5:

您应该使用什么来生成随机散列(与 md5 相同)是random_bytes()(在 PHP7 中引入)。生成与 MD5 长度相同的哈希:

bin2hex(random_bytes(16));

bin2hex(random_bytes(16));

If you are using PHP 5.x you can get this function by including random_compat library.

如果您使用的是 PHP 5.x,您可以通过包含random_compat 库来获得此功能。

回答by gogink

I ran into an interesting idea a couple of years ago.
Storing two hash values in the datebase, one generated with md5($a) and the other with sha($a). Then chek if both the values are corect. Point is, if the attacker broke your md5(), he cannot break your md5 AND sha in the near future.
Problem is: how can that concept be used with the token generating needed for your problem?

几年前我遇到了一个有趣的想法。
在数据库中存储两个哈希值,一个用 md5($a) 生成,另一个用 sha($a) 生成。然后检查两个值是否正确。重点是,如果攻击者破坏了您的 md5(),他将无法在不久的将来破坏您的 md5 和 sha。
问题是:这个概念如何与您的问题所需的令牌生成一起使用?

回答by M.A. Hanin

Define "unique". If you mean that two tokens cannot have the same value, then hashing isn't enough - it should be backed with a uniqueness test. The fact that you supply the hash algorithm with unique inputs does not guarantee unique outputs.

定义“独特”。如果您的意思是两个令牌不能具有相同的值,那么散列是不够的 - 应该通过唯一性测试来支持。您提供具有唯一输入的哈希算法这一事实并不能保证唯一的输出。

回答by webbiedave

To answer your question, the problem is you can't have a generator that is guaranteed random and unique as random by itself, i.e., md5(mt_rand())can lead to duplicates. What you want is "random appearing" unique values. uniqid gives the unique id, rand() affixes a random number making it even harder to guess, md5 masks the result to make it yet even harder to guess. Nothing is unguessable. We just need to make it so hard that they wouldn't even want to try.

要回答你的问题,问题是你不能有一个保证随机且唯一的生成器,它本身就是随机的,即md5(mt_rand())可能导致重复。您想要的是“随机出现”的唯一值。uniqid 给出了唯一的 id,rand() 附加了一个随机数使其更难猜测,md5 掩盖了结果以使其更难猜测。没有什么是不可猜测的。我们只需要让它变得如此困难,以至于他们甚至不想尝试。

回答by Lucian Minea

First, the scope of this kind of procedure is to create a key/hash/code, that will be unique for one given database. It is impossible to create something unique for the whole world at a given moment. That being said, you should create a plain, visible string, using a custom alphabet, and checking the created code against your database (table). If that string is unique, then you apply a md5()to it and that can't be guessed by anyone or any script. I know that if you dig deep into the theory of cryptographic generation you can find a lot of explanation about this kind of code generation, but when you put it to real usage it's really not that complicated.

首先,这种过程的范围是创建一个键/散列/代码,这对于一个给定的数据库是唯一的。在特定时刻为整个世界创造出独一无二的东西是不可能的。话虽如此,您应该创建一个普通的、可见的字符串,使用自定义字母表,并根据您的数据库(表)检查创建的代码。如果该字符串是唯一的,那么您对其应用 amd5()并且任何人或任何脚本都无法猜到。我知道如果你深入研究密码生成理论,你会发现很多关于这种代码生成的解释,但是当你把它付诸实际使用时,它真的没有那么复杂。

Here's the code I use to generate a simple 10 digit unique code.

这是我用来生成一个简单的 10 位唯一代码的代码。

$alphabet = "aA1!bB2@cC3#dD5%eE6^fF7&gG8*hH9(iI0)jJ4-kK=+lL[mM]nN{oO}pP\qQ/rR,sS.tT?uUvV>xX~yY|zZ`wW$";
$code = '';
$alplhaLenght = strlen($alphabet )-1;
for ($i = 1; $i <= 10; $i++) {
    $n = rand(1, $alplhaLenght );
    $code .= $alphabet [$n];
}

And here are some generated codes, although you can run it yourself to see it work:

这里有一些生成的代码,虽然你可以自己运行它来查看它的工作:

SpQ0T0tyO%
Uwn[MU][.
D|[ROt+Cd@
O6I|w38TRe

SpQ0T0tyO%
Uwn[MU][.
D|[ROt+Cd@
O6I|w38TRe

Of course, there can be a lot of "improvements" that can be applied to it, to make it more "complicated", but if you apply a md5()to this, it'll become, let's say "unguessable" . :)

当然,可以有很多“改进”可以应用于它,使其更加“复杂”,但是如果你将 amd5()应用于它,它会变得,让我们说“不可猜测”。:)

回答by Etamar Laron

MD5 is a decent algorithm for producing data dependentIDs. But in case you have more than one item which has the same bitstream (content), you will be producing two similar MD5 "ids".

MD5 是一种用于生成数据相关ID的不错算法。但是,如果您有多个具有相同比特流(内容)的项目,您将生成两个相似的 MD5“id”。

So if you are just applying it to a rand()function, which is guaranteed not to create the same number twice, you are quite safe.

因此,如果您只是将它应用于一个rand()函数,保证不会创建两次相同的数字,那么您就非常安全。

But for a stronger distribution of keys, I'd personally use SHA1 or SHAx etc'... but you will still have the problem of similar data leads to similar keys.

但是对于更强大的密钥分配,我个人会使用 SHA1 或 SHAx 等……但是您仍然会遇到类似数据导致类似密钥的问题。