I recently answered a question on Code Review: Resizing a discrete uniform CSRNG distribution and I was challenged to offer a proof for one of my suggestions, and I can't find one, possibly because I don't know how best to describe my suggestion.
As background, there is an (assumed) CSRNG RNGCryptoServiceProvider available that returns random bytes in the range [0, 256)
.
The objective is to return random values in a limited range [0, limit)
where limit <= 256
.
My suggestion is to:
- allocate a variable to store the previous value generated
- add a random value to it (from the CSRNG)
- modulo the result by the limit
- store the result to be used in the next request
- return the result
In my words, this returns a series of integer values where the differences between each is guaranteed (to the limits of the base CSRNG) to be uniformly distributed. Any modulo bias in the result is only relative to the previous result (not relative to 0).
In code (C#), I proposed:
private static IEnumerable<int> RandomWrap(int chunkSize, int limit)
{
int prev = 0;
foreach (byte b in RandomBytes(chunkSize))
{
prev = (prev + b) % limit;
yield return prev;
}
}
Does this code preserve the integrity of the CSRNG source? Can I prove it? Is there a reference I can use?