gpt4 book ai didi

c# - 在 C# 中创建加密随机数的最快、线程安全的方法?

转载 作者:行者123 更新时间:2023-11-30 19:59:25 24 4
gpt4 key购买 nike

注意到在多个线程上并行生成随机数时,加密随机数生成器不是线程安全的。使用的生成器是 RNGCryptoServiceProvider,它似乎会重复很长一段随机位(128 位)。重现此代码的代码如下所示。

除了使用锁来保护对 RNGCryptoServiceProvider 实例的访问(这会扼杀这里的整个速度点),有没有人有更快的方法来生成加密随机数?

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

最佳答案

documentation对于 RNGCryptoServiceProvider 状态:

This type is thread safe.

您的代码没有证明 RNGCryptoServiceProvider 不是线程安全的,因为您在多个线程中使用相同的数组。即使 RNGCryptoServiceProvider 是线程安全的,数组重用也不是线程安全的。

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

因此,如果您遇到性能问题,我会尝试的第一件事是一次请求更多数据并自行拆分。如果这还不够,请使用由系统 CSPRNG 播种的流密码。

关于c# - 在 C# 中创建加密随机数的最快、线程安全的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24046260/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com