0

I've been trying to simulate rolling a 6-faces dice in C#. I thought using RNGCSP was better than Random because it is more secure.

I tried using MSDN's example code to achieve this, but there are a few things that I didn't understand from the code:

  1. How do you generate 5 digit long numbers with RNGCSP?
  2. How do you generate numbers from 1 to 6 (excluding zeroes)?
Alexandre
  • 97
  • 11
  • How much security do you need to simulate a dice roll? – Preston Guillot Aug 09 '15 at 15:54
  • I need it to be completely random. – Alexandre Aug 09 '15 at 15:54
  • "How do you generate numbers from 1 to 6 (excluding zeroes)?" The example simply uses the [mod operator %](https://msdn.microsoft.com/en-us/library/0w4e0fzs.aspx?f=255&MSPPError=-2147217396): `return (byte)((randomNumber[0] % numberSides) + 1);` – Idle_Mind Aug 09 '15 at 19:48
  • 1
    Yes, the mod operator solves the dice problem and, with a little more work, the 5-digit problem to the satisfaction of most. However, if randomness is *very* important, there is something extra to consider. If the RNGCSP returns a byte, it can be from 0 to 255 in value. So you mod it 6 and add 1. But doing this, of the 256 possible values of that byte, values yielding a 1, 2, 3, or 4 using Idle_Mind's formula will each come up 43 out of 256 times. 5 and 6 will each come up only 42 out of 256 times. Therefore before taking the mod, you should throw out any byte value 252-255 and reroll it. – WDS Aug 09 '15 at 21:22
  • @Preston Guillot: If you're running an online casino, or similar, then your random numbers need to be 100% secure. If your dice rolls exhibit any bias then somebody, somewhere will notice and take you to the cleaners. – LukeH Oct 27 '15 at 12:19

1 Answers1

3

1. How do you generate 5 digit long numbers with RNGCSP?

For the numbers, you can use a range. You'll have to think of the lower bound yourself though. Ranges for number are treated in RNGCryptoServiceProvider.

So for a 5 digit number min would be 0 or 10000 and max would be 100000, because max is exclusive.

2. How do you generate numbers from 1 to 6 (excluding zeroes)?

Basically the same way, you generate a range [1, 7) where 7 - the max value - is exclusive.

If you just want a dice result you can just do something like this (untested!):

RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] singleByteBuf = new byte[1];
int max = Byte.MaxValue - Byte.MaxValue % 6;
while (true) {
    rng.GetBytes(singleByteBuf);
    int b = singleByteBuf[0];
    if (b < max) {
        return b % 6 + 1;
    }
 }

Basically the same idea, but is only requests 1 byte at a time from the RNGCryptoServiceProvider, so it doesn't waste 3 additional bytes.

Community
  • 1
  • 1
Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263