Reputation: 443
I am trying to implement a set of encode and decode steganography functions in C, where i use rand() to randomly scatter my data along an array.
I use rand to calculate a random index like so:
unsigned int getRandIndex(int size) {
return ((unsigned)(rand() * 8)) % size;
}
I seed rand like so:
unsigned long seed = time(NULL);
srand(seed);
I include the seed along with my data as a part of a header that contains a checksum and length.
The problem i have is that while decoding, when i seed the rand function again with the seed i decoded from the data, rand() tends to produce the slightest variations like so:
Index at encode: | Index at decode:
---------------------------------------------------------------------
.
.
.
At: 142568 | At: 142568
At: 155560 | At: 155552
-- --
At: 168184 | At: 168184
.
.
.
Messing up my decoded data.
Is this a limitation of the rand() function? I am 100% sure that the seed is being decoded correctly bit-for-bit as i have verified that.
Upvotes: 1
Views: 1001
Reputation: 140569
OpenBSD's implementation of rand
ignores all calls to srand
and instead provides automatically seeded, cryptographically strong random numbers as if you were using arc4random
; this is documented as an intentional deviation from the C standard. This demonstrates that even if your files are always decoded on the exact same computer that produced them, there's no guarantee rand
will do what you want.
If you need reproducible sequences of pseudorandom numbers, you should do what industrial grade statistics software does, which is ship your own PRNG and document your choice of algorithm. (See for instance the ?Random
help page for R.)
Also, since this is a steganography application, you need to use a cryptographically strong PRNG (also known as a stream cipher); merely statistically strong PRNGs like the Mersenne Twister are not good enough.
Upvotes: 1
Reputation: 222660
C 2018 7.22.2.2 2 says:
The
srand
function uses the argument as a seed for a new sequence of pseudo-random numbers to be returned by subsequent calls torand
. Ifsrand
is then called with the same seed value, the sequence of pseudo-random numbers shall be repeated.
This does not explicitly say the sequence is the same in different executions of the program, but I take that as understood. It does not, however, extend to different C implementations, including those that result from linking in a different version of the C standard library.
Upvotes: 5
Reputation: 117681
No. For reproducibility using rand
(which is not exactly specified and inherently uses global state) is terrible for multiple reasons:
you might use a different compiler/system, which may use a different RNG,
you might use the same compiler, but updated to a new version, which uses a different RNG,
you might use the same compiler, same version, but with an updated libc
, that uses a different RNG,
you use the same compiler and library version, but have any other non-deterministic call order of the RNG, including but not limited to:
a) some other source of randomness,
b) user input,
c) reordering of concurrency from run-to-run, or
d) any of the above in any of the libraries that you use.
Upvotes: 0