类似于/ dev / urandom与可配置种子的东西?

时间:2013-07-25 14:43:00

标签: linux

dd来自/dev/urandom以创建包含随机内容的文件。这很好用,但我希望能够通过使用相同的种子再次运行PRNG来稍后重现文件内容。是否存在暴露字符设备的可种子PRNG?

我正在使用最新的Linux 3.X内核。

6 个答案:

答案 0 :(得分:2)

/dev/urandom旨在尽可能无法预测。听起来你想要一个更传统的种子伪随机数发生器。

这是我刚用C写的一篇:

#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    char *endptr;
    unsigned long int seed;

    if (argc != 2 || *argv[1] == '\0') {
        fprintf(stderr, "usage: %s seed\n", argv[0]);
        return EXIT_FAILURE;
    }
    errno = 0;
    seed = strtoul(argv[1], &endptr, 0);
    if (errno != 0 || *endptr != '\0' || seed > UINT_MAX) {
        fprintf(stderr, "%s: invalid seed\n", argv[0]);
        return EXIT_FAILURE;
    }
    srandom((unsigned int) seed);

    while (1) {
        int i;
        long int randomnum = random();
        for (i = 0; i < sizeof randomnum; i++) {
            if (putchar((randomnum >> (i * CHAR_BIT)) & UCHAR_MAX) == EOF) {
                return EXIT_SUCCESS;
            }
        }
    }
}

这是一个程序,而不是设备文件,但其输出格式与/dev/urandom的格式相同。您可以将其中的输出传递到dd并省略if

如果您需要提供一个真正随机的种子来提供给该计划,您可以从/dev/urandom获取一个bash中的一个:

seed=$(od -vAn -N4 -tu4 </dev/urandom)

将4更换为机器上的sizeof(unsigned int)(可能是4)。

答案 1 :(得分:1)

取自urandom documentation

  

当Linux系统启动而没有太多的操作员交互时,   熵池可能处于相当可预测的状态。这减少了   熵池中的实际噪声量低于估计值。在   为了抵消这种影响,它有助于携带熵池   关闭和初创企业的信息。为此,请添加   以下行到Linux期间运行的相应脚本   系统启动顺序:

    echo "Initializing kernel random number generator..."
    # Initialize kernel random number generator with random seed 
    # from last shut-down (or start-up) to this start-up.  Load and 
    # then save 512 bytes, which is the size of the entropy pool.
    if [ -f /var/random-seed ]; then
            cat /var/random-seed >/dev/urandom
    fi
    dd if=/dev/urandom of=/var/random-seed count=1

答案 2 :(得分:1)

Python 3.9 random.randbytes + random.seed

我已经学会了停止对抗 Bash 无法做到的事情,而顺其自然:

randbytes() (
  python -c 'import random;import sys;random.seed(int(sys.argv[1]));sys.stdout.buffer.write(random.randbytes(int(sys.argv[2])))' "$@"
)

用法:

randbytes <seed> <nbytes>

例如:

randbytes 0 8 | hd

总是输出 8 个相同的伪随机字节,种子为 0:

00000000  cd 07 2c d8 be 6f 9f 62                           |..,..o.b|
00000008

可读的多行版本:Generating random string of seedable data

在我的 Lenovo ThinkPad P51 上,我可以在 0.5 秒内在 ramfs 中转储 1 亿字节。然而,如果我试图抛掉 10 亿,它就会爆炸:

Python int too large to convert to C int

所以要记住这一点。

比较:

time sudo dd if=/dev/urandom of=ramfs/test bs=4k count=24414

花费了 2.5 秒,所以它更慢,这并不奇怪,因为它是一个更随机的源,而 Python 生成器是确定性的,似乎是用 C 编写的。

在 Ubuntu 20.10、Linux 内核 5.8.0 上测试。

答案 3 :(得分:0)

/ dev / * random不使用种子,因为它们不是伪随机数生成器。它们提供来自环境的随机性(甚至使用硬件作为源,如键盘,中断,网络等)。在/ dev / urandom的情况下,种子和RNG仅在池耗尽时使用。但是当发生这种情况时,它仍然是不可预测的。

所以,不要从/ dev / * random中读取随机数。相反,使用bash工具生成随机数:

#! /bin/bash

# Seed the RNG
RANDOM = 1234

# Print 10 random numbers
for i in {1..10}
do
    echo $RANDOM
done

上述脚本每次都会打印相同的数字序列,因为种子是常量。

如果要生成字节,意味着0到255范围内的值,请使用printf而不是echo,并将您获得的随机数循环到该范围:

printf "\\x$(printf "%x" $(($RANDOM % 256)))"

如果您现在运行脚本并将输出重定向到文件,它将包含10个“随机”字节。

答案 4 :(得分:0)

检查ISO C rand()和srand()函数:

http://man7.org/linux/man-pages/man3/rand.3.html

答案 5 :(得分:-1)

如果您希望文件是随机的,但是在给定种子的情况下可以重现,您使用的是错误的工具。 / dev / urandom从环境中获取其随机性(传入和传出网络数据包的时间,磁盘访问等),所以即使你从相同的种子开始,你也很可能得到相同的随机数序列2连续几次。

您需要传统的(也称为纯软件)伪随机数生成器。 Mersenne Twister是一个很好的。{3}}。它应该使用您正在使用的语言implementation。或者只使用您的语言附带的伪随机数生成器。