生成加密安全令牌

fir*_*ire 75 php security openssl token

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

$token = md5(uniqid(mt_rand(), true));
Run Code Online (Sandbox Code Playgroud)

我已经读过这种方法不是加密安全的,因为它基于系统时钟,这openssl_random_pseudo_bytes将是一个更好的解决方案,因为它更难预测.

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

我推测这样的事情,但我不知道这是不对的......

$token = md5(openssl_random_pseudo_bytes(32));
Run Code Online (Sandbox Code Playgroud)

我应该传递给函数的长度是多少?

fir*_*ire 172

这是正确的解决方案:

$token = bin2hex(openssl_random_pseudo_bytes(16));

# or in php7
$token = bin2hex(random_bytes(16));
Run Code Online (Sandbox Code Playgroud)

  • PHP 5.x支持random_bytes()和random_int()https://github.com/paragonie/random_compat (4认同)
  • 您可能还需要`bin2hex(random_bytes($ length / 2))`,因为每个字节可以有2个十六进制字符,因此如果没有它,字符数将始终是$ length的两倍。 (3认同)
  • @AFriend同意。如果要创建一个生成字符串,字符串长度为$ length个字符(而不是关心字节大小),则需要传递random_bytes($ length / 2)个字符。 (2认同)

mjs*_*jsa 10

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

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

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

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


imi*_*ers 9

如果您有加密安全随机数生成器,则不需要对其输出进行散列.实际上你不想这样做.只是用

$token  = openssl_random_pseudo_bytes($BYTES,true)
Run Code Online (Sandbox Code Playgroud)

但是,$ BYTES需要多个字节的数据.MD5有一个128位散列,所以16个字节就可以了.

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

  • openssl_random_pseudo_bytes()的第二个参数应该是通过引用传递的变量.在openssl_random_pseudo_bytes之后,如果openssl能够使用加密强算法,那么该变量将为true或false.它不是用来告诉openssl使用加密强大的算法,它会尝试做任何事情. (26认同)