0

我编写了一个应该生成伪随机字符串的代码。我试图通过收集用户鼠标移动的熵来提高随机性。

这是我的代码:

// As described in the PHP documentation
function make_seed() {
    list($usec, $sec) = explode(' ', microtime());
    return (float) $sec + ((float) $usec * 100000);
}

function rand_string($entropy, $length, $chars) {
    mt_srand($entropy . make_seed()); // Here is the important line
    $return = '';
    $charlen = strlen($chars);
    for ($i=0;$i<$length;$i++) {
        $rand = mt_rand(0, $charlen) - 1;
        $return .= substr($chars, $rand, 1);
    }
    return $return;
}

$entropy = '18421828841384386426948169412548'; // Mouse movements, changes everytime
echo rand_string($entropy, 20, 'abcdefghijklmnopqrstuvwxz');

我运行了几次该功能。有些值非常频繁地出现,所以这是一个非常弱的功能。我不明白为什么。mt_srand 的参数有限制吗?它必须是一个数字吗?

编辑: mt_srand() 种子必须是 INT。

4

2 回答 2

1

mt_srand() 采用无符号 32 位整数来初始化 mersenne twister。
http://svn.php.net/viewvc/php/php-src/trunk/ext/standard/rand.c?revision=321634&view=markup

194     /* {{{ php_mt_srand
195     */
196     PHPAPI void php_mt_srand(php_uint32 seed TSRMLS_DC)
197     {
198     /* Seed the generator with a simple uint32 */
199     php_mt_initialize(seed, BG(state));
200     php_mt_reload(TSRMLS_C);
201     
202     /* Seed only once */
203     BG(mt_rand_is_seeded) = 1;
204     }
205     /* }}} */

我建议寻找底层系统的方法来收集熵/随机位。
这将是*nix 机器上的rngd + /dev/random和 Windows 下的CryptGenRandom或(更简单但更慢)CAPICOM Utilities.GetRandom()

根据您的需要,mcrypt_create_iv()也可能是一个不错的选择(可能与从 iv 创建“可读”字符串的东西结合使用)。

于 2013-02-28T15:34:46.233 回答
0

我编写了自己的随机字符串生成器,没有使用 php 的 rand() 函数。

function rs($length,$chars)
{
    $hex = sha1(microtime()); //contains hexadecimal string
    $return = '';
    $seedLen = strlen($chars); //length of the source characters string
    $posLen  = strlen($hex); //length of the hex string
    for($i=0;$i<$length;$i++){
        $idx_hex = $i % ($posLen-1); //make sure the address is in the hex string (if $i is too big)
        $pos = hexdec($hex[$idx_hex].$hex[$idx_hex+1]);
        $return .= $chars[$pos % $seedLen];
    }
    return $return;
}

它的工作方式是:它生成当前时间的 sha1 哈希(一个看起来像 06009da3e0d26f8569b65cb50a774bb6b431a777 的字符串)然后它一次从哈希中获取 2 个值,并将其用作 $chars 字符串中字符的十六进制“地址”。即在本例中,如果 $chars 字符串是“abcdefghijklmnopqrstuvwxyz”,那么“random”字符串中的第一个字符将是“g”——chars 字符串中索引为 06 的字母。限制:(1) 仅使用 $chars 字符串中的前 256 个字符(如果它长于 256 个字符)(2) 由于模运算符,此函数比 mt_rand() 慢。

编辑: mt_rand() 也使用模运算符,因此速度可能与此函数的顺序相同。我没有进行任何比较。

于 2013-02-28T15:30:23.020 回答