C#中是否允许加密随机生成器种子?

bob*_*ito 4 c# random prng visual-studio

似乎没有办法在C#中手动播种RNGCryptoServiceProvider.我可以在下面做一些简单的事情来获得可重复的randomBytes进行调试吗?

  RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
  byte[] randomBytes = new byte[20];
  rngCsp.GetBytes(randomBytes);
  MessageBox.Show(Convert.ToBase64String(randomBytes));
Run Code Online (Sandbox Code Playgroud)

我知道我可以手动输入20个字节,但这是一个痛苦,因为我真的需要超过20个.另外,我知道我可以使用非加密随机数发生器,但最后,我将需要最好的随机生成.

顺便说一下,我猜有些CPU有真正的随机生成,其中种子在物理上是不可能的,但我不认为我的CPU具有这种能力.我想知道是否有人确切知道我可以用我的CPU来重置RNGCryptoServiceProvider环境并欺骗RNGCryptoServiceProvider使用先前的种子...我想我可以设置我的时钟并重置一些"用户日志位"某处...我知道这不切实际,但想知道是否有人在这方面取得过成功(尽管微软的目标可能是防止这种情况).

drf*_*drf 7

没有办法播种RNGCryptoServiceProvider.为调试生成确定性值的一种解决方案是派生自己的类System.Security.Cryptography.RandomNumberGenerator(从(基类)开始实现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);
    }
}
Run Code Online (Sandbox Code Playgroud)

注意,实现使用Random种子为0 的标准实现,确保确定性结果.现在您可以使用此类代替RNGCryptoServiceProvider调试目的:

    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));
Run Code Online (Sandbox Code Playgroud)

编辑添加

我想知道是否有人确切知道我可以用我的CPU做什么来重置RNGCryptoServiceProvider环境并欺骗RNGCryptoServiceProvider使用先前的种子

在内部,RNGCryptoServiceProvider调用Win32 CryptGenRandom函数以使用加密随机值(源和附加信息)填充缓冲区.它不是基于单一种子.(虽然Win32 API允许调用者提供带有补充随机数据的种子,但.NET API不公开此功能.此上下文中种子的目的是提供应用程序可访问的附加熵,而不是强制一个确定性的序列.)CryptGenRandom文件说明:

为了形成随机数生成器的种子,调用应用程序提供它可能具有的位 - 例如,鼠标或键盘定时输入 - 然后将其与存储的种子和各种系统数据以及用户数据(例如进程ID和线程ID,系统时钟,系统时间,系统计数器,内存状态,可用磁盘集群,散列用户环境块.该结果用于对伪随机数发生器(PRNG)进行种子处理.在带有Service Pack 1(SP1)及更高版本的Windows Vista中,使用NIST特殊出版物800-90中指定的基于AES计数器模式的PRNG的实现.在Windows Vista,Windows Storage Server 2003和Windows XP中,使用联邦信息处理标准(FIPS)186-2中指定的PRNG.

结果是,"重置" RNGCryptoServiceProvider以强制它重复前一个序列是设计上不实用的方法.