How can I use RNGCryptoServiceProvider to generate a bridge?

In the game "Bridges" 52 different playing cards are played, which are randomly distributed among four players, each player ends with thirteen cards: the so-called "deal". About slightly less than 2 ^ 96 Fashion deals are possible . In this paper the requirements for the program, which generates a random transaction, described as follows:

  • The software should be able to generate all possible bridge trades as this is also possible with manual control.
  • The software should generate every trade with equal probability, without affecting the board number, previous hands, or any other circumstance.
  • It is impossible to predict trades, even after reviewing all other trades in the session.

This document states that pseudo-random generators cannot be used to create trades, as looking at the first elements of the pseudo-random sequence will compute the seed used and thus allow the hacker to predict the trades that will follow.

Also, since most pseudo-random generators take a 32-bit seed, it should be followed that these generators will be capable of producing at best 2 ^ 32 different Bridge transactions as opposed to the required 2 ^ 96 and that, following the so-called Birthday Paradox , it is likely that the same trade will be executed after the square root of 2 ^ 32 trades.

The author of the document, which describes the requirements of a bridge transaction application, wrote a program used worldwide to generate random transactions that generates a 96-bit seed using random human typing on a keyboard. For fourteen years, there have been no flaws in this approach.

I would like to write a routine that does not require the use of human input to generate the required seed.

Enters RNGCryptoServiceProvider

. I used this using the code below to generate random numbers, first in the range 1 to 52, then in the range 1 to 51, and so on until there is one card left.

Testing the resulting trades I'm pretty confident that this code is capable of making any trade with the same probability and the probability that any card ending with one of the four players is 0.25.

But since the strength of the seed used in the RNGCryptoServiceProvider is unknown to me. I am wondering if:

  • This code can or can be adapted to create 2 ^ 96 different trades.
  • This code for the next trade will not be predictable.

EDIT The method for getting random numbers previously mentioned in this question was flawed. This takes away from the main issue if this code is capable of producing 2 ^ 96 different bridge trades. I replaced the random number generator with the one published by Steven Taub and Sean Farkas in MSDN magazine

Code used to get a cryptographically secure random number in the ranges 1-52, 1-51, and so on up to 1-2, taken from this site

     /// <summary>
/// Returns a random number within a specified range.
/// </summary>
/// <returns>
/// A 32-bit signed integer greater than or equal to <paramref name="minValue"/> and less than <paramref name="maxValue"/>; that is, the range of return values includes <paramref name="minValue"/> but not <paramref name="maxValue"/>. If <paramref name="minValue"/> equals <paramref name="maxValue"/>, <paramref name="minValue"/> is returned.
/// </returns>
/// <param name="minValue">The inclusive lower bound of the random number returned.</param>
/// <param name="maxValue">The exclusive upper bound of the random number returned. <paramref name="maxValue"/> must be greater than or equal to <paramref name="minValue"/>.</param>
/// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="minValue"/> is greater than <paramref name="maxValue"/>.</exception>
public override Int32 Next(Int32 minValue, Int32 maxValue)
{
    if (minValue > maxValue) throw new ArgumentOutOfRangeException("minValue");
    if (minValue == maxValue) return minValue;
    Int64 diff = maxValue - minValue;

    while (true)
    {
        //The cryptoProvider is of type RNGCryptoServiceProvider.
        cryptoProvider.GetBytes(uint32Buffer); //The uint32Buffer has a size of 4 bytes.
        UInt32 rand = BitConverter.ToUInt32(uint32Buffer, 0);

        Int64 max = (1 + (Int64)UInt32.MaxValue);
        Int64 remainder = max % diff;
        if (rand < max - remainder)
        {
            return (Int32)(minValue + (rand % diff));
        }
    }
}

      

+3


source to share


1 answer


Once you have a random number generator (RNG) that is "truly homogeneous", follow these steps:

  • Initialize the RNG with seeds based on an external source. This could be keyboard input, program start time, or a number of other things. From my research, it looks like the RNGCryptoServiceProvider already fulfills this role.

  • Most importantly, at (frequent) intervals, draw the number from the RNG. Just drop the number, the important part is that you "looped" the RNG. Optionally, you can randomize the intervals to increase unpredictability. More loops are better, so I would choose the maximum interval as low as you feel you can walk.

    • There are two options for random spacing: (a) use the weaker RNG (which they use) and (b) ignore it. In a gaming machine, user input (pressing "SPIN") causes the actual RNG output. Combined with a reasonably fast cycling interval, it was considered unpredictable.

  • (Slightly optional) Don't draw all the numbers on the line. Wait a while (so the RNG can cycle through the number of times) before drawing the next number (or set of numbers). Since the original draw is most likely based on user input, you should go away to draw them all at once. However, it can't hurt.



This is a process used in the gambling (gambling) industry where unpredictable hydraulic fractures are highly regulated (and of course required). This method uses 500 cards (out of 100 separate decks) to be played. Note that the RNGs used usually take 32-bit seeds and are perfectly acceptable.

+5


source







All Articles