Faraz
Faraz

Reputation: 443

Will the rand() function ALWAYS produce the same result with the same seed?

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

Answers (3)

zwol
zwol

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

Eric Postpischil
Eric Postpischil

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 to rand. If srand 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

orlp
orlp

Reputation: 117681

No. For reproducibility using rand (which is not exactly specified and inherently uses global state) is terrible for multiple reasons:

  1. you might use a different compiler/system, which may use a different RNG,

  2. you might use the same compiler, but updated to a new version, which uses a different RNG,

  3. you might use the same compiler, same version, but with an updated libc, that uses a different RNG,

  4. 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

Related Questions