php 生成加密安全令牌

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18830839/
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 18:17:20  来源:igfitidea点击:

Generating cryptographically secure tokens

phpsecurityopenssltoken

提问by fire

In order to generate a 32 character token for access to our API we currently use:

为了生成 32 个字符的令牌以访问我们的 API,我们目前使用:

$token = md5(uniqid(mt_rand(), true));

I have read that this method is not cryptographically secure as it's based on the system clock, and that openssl_random_pseudo_byteswould be a better solution as it would be harder to predict.

我已经读到这种方法在密码学上并不安全,因为它基于系统时钟,这openssl_random_pseudo_bytes将是一个更好的解决方案,因为它更难预测。

If this is the case, what would the equivalent code look like?

如果是这种情况,等效代码会是什么样子?

I presume something like this, but I don't know if this is right...

我猜是这样的,但我不知道这是否正确......

$token = md5(openssl_random_pseudo_bytes(32));

Also what length makes sense that I should pass to the function?

还有什么长度有意义,我应该传递给函数?

回答by fire

Here is the correct solution:

这是正确的解决方案:

$token = bin2hex(openssl_random_pseudo_bytes(16));

# or in php7
$token = bin2hex(random_bytes(16));

回答by mjsa

If you want to use openssl_random_pseudo_bytes it is best to use CrytoLib's implementation, this will allow you to generate all alphanumeric characters, sticking bin2hex around openssl_random_pseudo_bytes will just result in you getting A-F (caps) and numbers.

如果您想使用 openssl_random_pseudo_bytes 最好使用 CrytoLib 的实现,这将允许您生成所有字母数字字符,在 openssl_random_pseudo_bytes 周围粘贴 bin2hex 只会导致您获得 AF(大写)和数字。

Replace path/to/ with where you put the cryptolib.php file (you can find it on GitHub at: https://github.com/IcyApril/CryptoLib)

将 path/to/ 替换为您放置 cryptolib.php 文件的位置(您可以在 GitHub 上找到它:https://github.com/IcyApril/CryptoLib

<?php
  require_once('path/to/cryptolib.php');
  $token = CryptoLib::randomString(16);
?>

The full CryptoLib documentation is available at: https://cryptolib.ju.je/. It covers a lot of other random methods, cascading encryption and hash generation and validation; but it's there if you need it.

完整的 CryptoLib 文档位于:https://cryptolib.ju.je/ 。它涵盖了许多其他随机方法,级联加密和哈希生成和验证;但如果你需要它,它就在那里。

回答by imichaelmiers

If you have a cryptographically secure random number generator, you don't need to hash it's output. In fact you don't want to. Just use

如果您有加密安全的随机数生成器,则无需对其输出进行哈希处理。事实上你不想。只需使用

$token  = openssl_random_pseudo_bytes($BYTES,true)

Where $BYTES is however many bytes of data you want. MD5 has a 128bit hash, so 16 bytes will do.

其中 $BYTES 是您想要的许多字节的数据。MD5 有一个 128 位的哈希值,所以 16 个字节就可以了。

As a side note, none of the functions you call in your original code are cryptographically safe, most are harmful enough that using just one would break be insecure even if combined with secure other functions. MD5 has security issues(though for this application they may not be relevant). Uniqid not just doesn't generate cryptographically random bytes by default (since it uses the system clock), the added entropy you pass in is combined using a linear congruent generator, which is not cryptographically secure. In fact, it probably means one could guess all your API keys given access to a few of them even if they had no idea the value of your server clock. Finally, mt_rand(), what you use as the extra entropy, is not a secure random number generator either.

附带说明一下,您在原始代码中调用的所有函数都不是加密安全的,大多数都是有害的,即使与其他安全函数结合使用,仅使用一个函数也会破坏不安全。MD5 存在安全问题(尽管对于此应用程序,它们可能不相关)。Uniqid 不仅默认不生成加密随机字节(因为它使用系统时钟),您传入的附加熵是使用线性全等生成器组合的,这在加密上是不安全的。事实上,这可能意味着即使他们不知道你的服务器时钟的值,你也可以猜测你所有的 API 密钥,并可以访问其中的一些。最后,您用作额外熵的 mt_rand() 也不是安全的随机数生成器。

回答by Daro from Poland

Reliable passwords You can only make from asciicharacters a-zA-Zand numbers 0-9. To do that best way is using only cryptographically secure methods, like random_int()or random_bytes()from PHP7. Rest functions as base64_encode()You can use only as support functions to make reliability of string and change it to ASCIIcharacters.

可靠的密码您只能使用ascii字符a-zA-Z数字 0-9。要做到这一点,最好的方法是仅使用加密安全的方法,例如PHP7 中的 random_int()random_bytes()。Rest 函数作为base64_encode()您只能用作支持函数来提高字符串的可靠性并将其更改为ASCII字符。

mt_rand()is not secure and is very old. From any string You must use random_int(). From binary string You should use base64_encode()to make binary string reliable or bin2hex, but then You will cut byte only to 16 positions (values). See my implementation of this functions.It uses all languages.

mt_rand()不安全,而且很旧。从任何字符串您必须使用 random_int()。从二进制字符串你应该使用base64_encode()来使二进制字符串可靠或 bin2hex,但是你只会将字节剪切到 16 个位置(值)。 查看我对这个函数的实现。它使用所有语言。