为了生成32个字符的令牌以访问我们目前使用的API:
$token = md5(uniqid(mt_rand(), true));
我已经读过这种方法不是加密安全的,因为它基于系统时钟,openssl_random_pseudo_bytes
是更好的解决方案,因为它更难预测。
如果是这种情况,等效代码会是什么样的?
我认为这样的事情,但我不知道这是否正确......
$token = md5(openssl_random_pseudo_bytes(32));
我应该传递给函数的长度是多少才有意义?
答案 0 :(得分:156)
这是正确的解决方案:
$token = bin2hex(openssl_random_pseudo_bytes(16));
# or in php7
$token = bin2hex(random_bytes(16));
答案 1 :(得分:10)
如果你想使用openssl_random_pseudo_bytes,最好使用CrytoLib的实现,这将允许你生成所有字母数字字符,在openssl_random_pseudo_bytes周围粘贴bin2hex只会导致你获得A-F(上限)和数字。
将path / to替换为您放置cryptolib.php文件的位置(您可以在GitHub上找到它:https://github.com/IcyApril/CryptoLib)
<?php
require_once('path/to/cryptolib.php');
$token = CryptoLib::randomString(16);
?>
完整的CryptoLib文档位于:https://cryptolib.ju.je/。它涵盖了许多其他随机方法,级联加密和哈希生成和验证;但是如果你需要它就在那里。
答案 2 :(得分:8)
如果您有加密安全随机数生成器,则无需对其输出进行散列。实际上你不想这样做。 只需使用
$token = openssl_random_pseudo_bytes($BYTES,true)
其中$ BYTES是您想要的大量字节数据。 MD5有一个128位的散列,所以16个字节就可以了。
作为旁注,您在原始代码中调用的函数都不是加密安全的,大多数都是有害的,即使与安全的其他函数结合使用,只使用一个函数会破坏不安全。 MD5存在安全问题(尽管对于此应用程序,它们可能不相关)。 Uniqid默认情况下不会生成加密随机字节(因为它使用系统时钟),所传入的附加熵使用线性全等生成器进行组合,该生成器不具有加密安全性。事实上,它可能意味着即使他们不知道您的服务器时钟的价值,也可以猜测所有API密钥的访问权限。最后,mt_rand(),你用作额外熵,也不是一个安全的随机数发生器。
答案 3 :(得分:-1)
可靠密码您只能使用 ascii 字符 a-zA-Z 和数字0-9 。要做到这一点,最好的方法是使用加密安全方法,例如PHP7中的 random_int()或 random_bytes()。其余功能为 base64_encode()您只能将其用作支持函数,以使字符串可靠,并将其更改为 ASCII 字符。
mt_rand()不安全且非常老。 从任何字符串您必须使用random_int()。从二进制字符串您应该使用base64_encode()使二进制字符串可靠或bin2hex,但是然后您将字节仅切换到16个位置(值)。 See my implementation of this functions.它使用所有语言。