cwe*_*ton 26 .net c# asp.net security random
在寻找生成真正随机数的最佳尝试时,我偶然发现了这个代码示例.
在这个片段上寻找意见.
using System;
using System.Security.Cryptography;
private static int NextInt(int min, int max)
{
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] buffer = new byte[4];
rng.GetBytes(buffer);
int result = BitConverter.ToInt32(buffer, 0);
return new Random(result).Next(min, max);
}
Run Code Online (Sandbox Code Playgroud)
资料来源:http://www.vcskicks.com/code-snippet/rng-int.php
这比使用滴答计数种子更受欢迎,例如:
Random rand = new Random(Environment.TickCount);
rand.Next(min, max);
Run Code Online (Sandbox Code Playgroud)
注意:
我不是在寻找第三方随机数据提供者,例如Random.org,因为这种依赖对应用程序来说是不现实的.
Luk*_*keH 22
好吧,使用RNGCryptoServiceProvider给你一个不可思议的加密力量种子,而Environment.TickCount理论上是可预测的.
当NextInt快速连续多次调用您的方法时,另一个重要区别是显而易见的.使用RNGCryptoServiceProvider将Random每次使用不同的加密强度数对种子进行播种,这意味着它将继续为每次调用返回不同的随机数.使用每次使用相同数字TickCount播种Random对象的风险(如果在同一"tick"期间多次调用该方法),这意味着它将继续为每个调用返回相同(假设随机)的数字.
如果你真的需要真正随机的数字,那么你就不应该使用计算机来生成它们:你应该测量放射性衰变或类似的东西,真正无法预测.
不要使用你的代码.您的解决方案是错误的,并产生差的随机数.我建议我的解决方案,它生成加密强大的随机数:
public class SecureRandom : RandomNumberGenerator
{
private readonly RandomNumberGenerator rng = new RNGCryptoServiceProvider();
public int Next()
{
var data = new byte[sizeof(int)];
rng.GetBytes(data);
return BitConverter.ToInt32(data, 0) & (int.MaxValue - 1);
}
public int Next(int maxValue)
{
return Next(0, maxValue);
}
public int Next(int minValue, int maxValue)
{
if (minValue > maxValue)
{
throw new ArgumentOutOfRangeException();
}
return (int)Math.Floor((minValue + ((double)maxValue - minValue) * NextDouble()));
}
public double NextDouble()
{
var data = new byte[sizeof(uint)];
rng.GetBytes(data);
var randUint = BitConverter.ToUInt32(data, 0);
return randUint / (uint.MaxValue + 1.0);
}
public override void GetBytes(byte[] data)
{
rng.GetBytes(data);
}
public override void GetNonZeroBytes(byte[] data)
{
rng.GetNonZeroBytes(data);
}
}
Run Code Online (Sandbox Code Playgroud)
我真的不建议使用提供的示例。虽然RNGCryptoServiceProvider返回真正好的随机(或至少应该),但对于Random. 此外 - 不知道是否Random(value)针对 返回的值创建真正的双射Next(...)。此外 - 不能保证Next(min, max)以真正随机的方式返回值(意味着数字命中每个值的机会相等)。
我首先将问题分解为在区间 0 - max(不包括)中获取一个数字。然后,我将使用最接近的 2 次幂来获得 0 - (2^n - 1) 范围内的随机值。现在,您在这里绝对不能做的一件事是使用模来获得首选范围内的数字,例如rand(0 - (2^n - 1)) % max,因为这样做实际上会增加获得较低范围内数字的机会。
示例:max = 3, n = 2 (0 - (2^2 - 1)) % 2, 数字 (0, 1, 2, 3),模数 (0, 1, 2, 0) 后的对应值。看到我们两次命中 0,这是非常糟糕的随机性。
因此,解决方案是使用加密随机数获取最接近 2 的幂的值,如果该值超出最大范围,则重复过程(获取另一个加密随机数)直到该值在给定范围内。这将是一个更好的算法。
| 归档时间: |
|
| 查看次数: |
24780 次 |
| 最近记录: |