RNGCryptoServiceProvider

RNGCryptoServiceProvider

本文介绍了C# 中不允许加密随机生成器种子?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

似乎没有办法在 C# 中手动为 RNGCryptoServiceProvider 设置种子.我真的没有什么简单的方法可以在下面获得可重复的随机字节以进行调试吗?

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

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

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.

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

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

推荐答案

没有办法为 RNGCryptoServiceProvider 设定种子.为调试生成确定性值的一种解决方案是派生您自己的类,该类从 System.Security.Cryptography.RandomNumberGenerator(RNGCryptoServiceProvider 的基类)实现:

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

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

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

编辑添加

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

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

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:

为了形成随机数生成器的种子,调用应用程序提供它可能具有的位(例如鼠标或键盘计时输入),然后将这些位与存储的种子和各种系统数据以及用户数据(例如进程 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 以强制它重复之前的序列,从设计上来说,这不是一种实用的方法.

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

这篇关于C# 中不允许加密随机生成器种子?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-13 07:44