Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

no cryptography random generator seed allowed in C#?

It seems that there is no way to manually seed the RNGCryptoServiceProvider in C#. Is there really nothing simple I can do below to get repeatable randomBytes here for debugging?

  RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
  byte[] randomBytes = new byte[20];
  rngCsp.GetBytes(randomBytes);
  MessageBox.Show(Convert.ToBase64String(randomBytes));

I know that I could manually enter the 20 bytes, but this is a pain since I really need many more than 20. Also, I know that I could use the non-cryptography random number generator, but, in the end, I will need the best random generation.

By the way, I would guess some CPUs have true random generation built in where seeding is not physically possible, but I don't think my CPU has this capability. I wonder if anybody knows exactly what I could do with my CPU to reset the RNGCryptoServiceProvider environment and trick RNGCryptoServiceProvider into using a prior seed...I imagine I could set my clock back and reset some "user log bits" somewhere...I know this wouldn't be practical, but wonder if anybody has ever been successful at this (even though Microsoft's goal is probably to prevent this).

like image 289
bobuhito Avatar asked Dec 15 '22 03:12

bobuhito


1 Answers

There is not a means to seed the RNGCryptoServiceProvider. One solution to generating deterministic values for debugging is to derive your own class that implements from System.Security.Cryptography.RandomNumberGenerator (the base class for RNGCryptoServiceProvider):

class DeterministicRandomGenerator : System.Security.Cryptography.RandomNumberGenerator
{
    Random r = new Random(0);
    public override void GetBytes(byte[] data)
    {
        r.NextBytes(data);
    }
    public override void GetNonZeroBytes(byte[] data)
    {
        // simple implementation
        for (int i = 0; i < data.Length; i++)
            data[i] = (byte)r.Next(1, 256);
    }
}

Note the implementation uses the standard Random implementation with a seed of 0, ensuring deterministic results. Now you can use this class in place of RNGCryptoServiceProvider for debugging purposes:

    RandomNumberGenerator rngCsp = 
#if DEBUG
    new DeterministicRandomGenerator(); // get deterministic values if debugging
#else
    new RNGCryptoServiceProvider(); // otherwise, use CryptoRNG
#endif
    byte[] randomBytes = new byte[20];
    rngCsp.GetBytes(randomBytes);
    MessageBox.Show(Convert.ToBase64String(randomBytes));

Edited to add

I wonder if anybody knows exactly what I could do with my CPU to reset the RNGCryptoServiceProvider environment and trick RNGCryptoServiceProvider into using a prior seed

Internally, RNGCryptoServiceProvider calls the Win32 CryptGenRandom function to fill the buffer with cryptographically-random values (Source and additional information). It is not based on a single seed. (Although the Win32 API allows the caller to provide a seed with supplemental random data, the .NET API does not expose this functionality. The purpose of a seed in this context is to provide additional entropy the application has access to, rather than to force a deterministic sequence.) The CryptGenRandom documentation states that:

To form the seed for the random number generator, a calling application supplies bits it might have—for instance, mouse or keyboard timing input—that are then combined with both the stored seed and various system data and user data such as the process ID and thread ID, the system clock, the system time, the system counter, memory status, free disk clusters, the hashed user environment block. This result is used to seed the pseudorandom number generator (PRNG). In Windows Vista with Service Pack 1 (SP1) and later, an implementation of the AES counter-mode based PRNG specified in NIST Special Publication 800-90 is used. In Windows Vista, Windows Storage Server 2003, and Windows XP, the PRNG specified in Federal Information Processing Standard (FIPS) 186-2 is used.

The result is that "resetting" the RNGCryptoServiceProvider to coerce it into repeating a former sequence is, by design, not a practical approach.

like image 57
drf Avatar answered Dec 27 '22 09:12

drf