我dd
来自/dev/urandom
以创建包含随机内容的文件。这很好用,但我希望能够通过使用相同的种子再次运行PRNG来稍后重现文件内容。是否存在暴露字符设备的可种子PRNG?
我正在使用最新的Linux 3.X内核。
答案 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()函数:
答案 5 :(得分:-1)
如果您希望文件是随机的,但是在给定种子的情况下可以重现,您使用的是错误的工具。 / dev / urandom从环境中获取其随机性(传入和传出网络数据包的时间,磁盘访问等),所以即使你从相同的种子开始,你也很可能得到相同的随机数序列2连续几次。
您需要传统的(也称为纯软件)伪随机数生成器。 Mersenne Twister是一个很好的。{3}}。它应该使用您正在使用的语言implementation。或者只使用您的语言附带的伪随机数生成器。