RNGCryptoServiceProvider

RNGCryptoServiceProvider

本文介绍了最快,线程安全的方式来创建在C#中加密的随机数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意到,在以上的多个线程并行生成随机数,当加密的随机数发生器不是线程安全。使用的发电机 RNGCryptoServiceProvider ,它似乎重复随机位(128位)长的舒展。复制此代码如下所示。

Noticed that the crypto-random number generator isn't thread safe when generating random numbers in parallel over multiple threads. The generator used is RNGCryptoServiceProvider and it appears to repeat long stretches of random bits (128 bits). The code to reproduce this is shown below.

用锁来保护访问 RNGCryptoServiceProvider 实例短( ?它可以杀死这里的整个速度点),没有任何人有到发电机加密的随机数更快的方法

Short of using a lock to guard access to the RNGCryptoServiceProvider instance (which kills the whole speed point here), does anyone have a faster way to generator crypto-random numbers?

using System;
using System.Runtime.Caching;
using System.Security.Cryptography;
using System.Threading.Tasks;

namespace ParallelRandomness
{
    class Program
    {
        static void Main(string[] args)
        {
            var test = new Test();
            Console.Write("Serialized verion running ...  ");
            test.Run(false);
            Console.WriteLine();
            Console.Write("Parallelized verion running ...  ");
            test.Run(true);
            Console.WriteLine(Environment.NewLine + "Done.");
            Console.ReadLine();
        }
    }

    class Test
    {
        private readonly RNGCryptoServiceProvider _rng = new RNGCryptoServiceProvider();
        private readonly byte[] _randomBytes = new byte[128 / 8];
        private int collisionCount = 0;
        private readonly object collisionCountLock  = new object();

        public void Run(bool parallel)
        {
            const int numOfRuns = 100000;
            const int startInclusive = 1;
            const int endExclusive = numOfRuns + startInclusive;
            if (parallel)
                Parallel.For(startInclusive, endExclusive, x => GenRandomByteArrays(x));
            else
            {
                for (var i = startInclusive; i < endExclusive; i++)
                    GenRandomByteArrays(i);
            }
        }

        private void GenRandomByteArrays(long instance)
        {
            _rng.GetBytes(_randomBytes);
            var randomString = Convert.ToBase64String(_randomBytes);
            var cache = MemoryCache.Default;
            if (cache.Contains(randomString))
            {
                // uh-oh!
                lock (collisionCountLock)
                {
                    Console.WriteLine(Environment.NewLine + "Instance {0}: Collision count={1}. key={2} already in cache. ", instance, ++collisionCount, randomString);
                }
            }
            else
            {
                MemoryCache.Default.Add(randomString, true, DateTimeOffset.UtcNow.AddMinutes(5));
                Console.Write(instance % 2 == 0 ? "\b-" : "\b|"); // poor man's activity indicator
            }
        }
    }
}


推荐答案

RNGCryptoServiceProvider 规定:

这类型是线程安全的。

您的代码不表明 RNGCryptoServiceProvider 不是线程安全的,因为你使用多个线程在同一阵列。这阵再利用是不是线程安全的,即使 RNGCryptoServiceProvider

Your code doesn't demonstrate that RNGCryptoServiceProvider is not thread-safe, since you use the same array in multiple threads. That array reuse is not thread-safe even if RNGCryptoServiceProvider is.

对于性能我想指出,创建 RNGCryptoServiceProvider 的新实例是非常便宜的。昂贵的部分是 GetBytes会的每个调用的开销。

Regarding performance I want to note that creating a new instance of RNGCryptoServiceProvider is very cheap. The expensive part is the per-call overhead of GetBytes.

所以,如果你有性能问题,请第一件事我想尝试一次过被要求更多的数据和自己分裂它。如果这还不够,使用系统CSPRNG种子流密码。

So if you have performance trouble, the first thing I'd try is asking for more data in one go and splitting it yourself. If that's still not enough, use a stream cipher seeded by the system CSPRNG.

这篇关于最快,线程安全的方式来创建在C#中加密的随机数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 18:00