I'm dd
'ing from /dev/urandom
in order to create files with random contents. This works well, but I would like to be able to reproduce the file contents at some later point by running the PRNG again with the same seed. Is there any seedable PRNG which exposes a character device?
I'm using recent Linux 3.X kernels.
/dev/urandom
is designed to be as unpredictable as possible. It sounds like you want a more conventional seeded pseudorandom number generator.
Here's one I just wrote in 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;
}
}
}
}
This is a program, not a device file, but its output is the same format as you'd get from /dev/urandom
. You can pipe the output from it into dd
and omit if
.
If you need to come up with a truly random seed to supply to the program, you can get one in bash from /dev/urandom
like this:
seed=$(od -vAn -N4 -tu4 </dev/urandom)
Replace 4 with whatever sizeof(unsigned int)
is on your machine (it's probably 4).
Python 3.9 random.randbytes
+ random.seed
I've learnt to stop fighting what Bash can't do and just go with the flow:
randbytes() (
python -c 'import random;import sys;random.seed(int(sys.argv[1]));sys.stdout.buffer.write(random.randbytes(int(sys.argv[2])))' "$@"
)
Usage:
randbytes <seed> <nbytes>
e.g.:
randbytes 0 8 | hd
always outputs 8 identical pseudo-random bytes with seed 0:
00000000 cd 07 2c d8 be 6f 9f 62 |..,..o.b|
00000008
Readable multiline version at: Generating random string of seedable data
On my Lenovo ThinkPad P51, I can dump 100 million bytes in ramfs in 0.5s. however, if I try to dump 1 billion it blows up with:
Python int too large to convert to C int
so it is something to keep in mind.
For comparison:
time sudo dd if=/dev/urandom of=ramfs/test bs=4k count=24414
took 2.5s, so it is slower, which is not surprising as it is a more random source, while the Python generator is deterministic and appears to be written in C.
Tested on Ubuntu 20.10, Linux kernel 5.8.0.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With