C#中不允许使用密码随机生成器种子



似乎没有办法在C#中手动为RNGCryptoServiceProvider种子。下面真的没有什么简单的方法可以在这里获得可重复的randomBytes进行调试吗?

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

我知道我可以手动输入20个字节,但这很痛苦,因为我真的需要20个以上。此外,我知道我可以使用非密码学随机数生成器,但最终,我需要最好的随机数生成器。

顺便说一句,我想有些CPU内置了真正的随机生成,在物理上不可能进行播种,但我认为我的CPU没有这种能力。我想知道是否有人确切地知道我可以用我的CPU做什么来重置RNGCryptoServiceProvider环境,并诱骗RNGCryptoServiceProvider使用先前的种子。。。我想我可以把时钟调回来,在某个地方重置一些"用户日志位"。。。我知道这并不实际,但我想知道是否有人在这方面取得过成功(尽管微软的目标可能是防止这种情况发生)。

没有办法为RNGCryptoServiceProvider播种。生成用于调试的确定性值的一个解决方案是从System.Security.Cryptography.RandomNumberGeneratorRNGCryptoServiceProvider的基类)派生自己的类:

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);
    }
}

请注意,该实现使用种子为0的标准Random实现,以确保结果具有确定性。现在您可以使用这个类来代替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));

编辑以添加

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

在内部,RNGCryptoServiceProvider调用Win32 CryptGenRandom函数,用加密随机值(Source和其他信息)填充缓冲区。它不是基于一颗种子。(尽管Win32 API允许调用方提供具有补充随机数据的种子,但.NET API不公开此功能。此上下文中种子的目的是提供应用程序可以访问的附加熵,而不是强制使用确定性序列。)CryptGenRandom文档指出:

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

结果是,从设计上讲,"重置"RNGCryptoServiceProvider以迫使其重复以前的序列不是一种实用的方法。

此外,我知道我可以使用非密码学随机数生成器,但最终,我需要最好的随机数生成器。

出于测试目的,使用Mersenne Twister或类似的可种子PRNG(仅在需要可重复结果的测试中),其他一切都使用RCPCryptoServiceProvider

另一种选择是预生成一批randomBytes阵列,并将它们保存到磁盘上,以便在测试阶段使用。这提供了一个优点,即在保持RCP CSP的相同随机分布和其他特性的同时,提供了可重复性。此外,忘记删除临时代码比忘记不包含无关文件更容易。

最新更新