似乎没有办法在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.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);
}
}
请注意,该实现使用种子为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的相同随机分布和其他特性的同时,提供了可重复性。此外,忘记删除临时代码比忘记不包含无关文件更容易。