no cryptography random generator seed allowed in C#?

这一生的挚爱 提交于 2019-12-23 12:48:01

问题


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


回答1:


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.




回答2:


Also, I know that I could use the non-cryptography random number generator, but, in the end, I will need the best random generation.

Use a Mersenne Twister or similar as a seedable PRNG for testing purposes - only in those tests where a repeatable result is required - and the RCPCryptoServiceProvider for everything else.

Another alternative is to pre-generate a batch of randomBytes arrays and save those to disk for use in your testing phase. This gives the advantage of giving you repeatability while retaining the same random distribution and other characteristics of the RCP CSP. Also it's easier to forget to remove temporary code than it is to forget NOT to include extraneous files.



来源:https://stackoverflow.com/questions/20318078/no-cryptography-random-generator-seed-allowed-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!