Dex*_*ter 6 c# random rngcryptoserviceprovider
我目前正在创建一个随机密码是这样的:
public static int getRandomNumber(int maxNumber)
{
if (maxNumber < 1)
throw new System.Exception("The maxNumber value should be greater than 1");
byte[] b = new byte[4];
new System.Security.Cryptography.RNGCryptoServiceProvider().GetBytes(b);
int seed = (b[0] & 0x7f) << 24 | b[1] << 16 | b[2] << 8 | b[3];
System.Random r = new System.Random(seed);
return r.Next(1, maxNumber);
}
Run Code Online (Sandbox Code Playgroud)
一些可能的问题?这是一个静态函数,有一些奇怪的种子模式可能不安全,仍然使用System.Random().
使用上面的随机数生成器,我以这种低效的方式创建一个字符串:
validCharacters = "abcdefghjkmnoxyz023456789#!@";
Run Code Online (Sandbox Code Playgroud)
然后使用有效数组循环并获取"createPassword(length)"类型字符串(注意使用不包含容错字符的字符集,如1 i等).
这是如何做到的,还是有更简单,更安全,更有效的方式?
为了生成随机数,您可以返回余数seed除以maxNumber:
public static int getRandomNumber(int maxNumber)
{
if (maxNumber < 1)
throw new System.Exception("The maxNumber value should be greater than 1");
byte[] b = new byte[4];
new System.Security.Cryptography.RNGCryptoServiceProvider().GetBytes(b);
int seed = (b[0] & 0x7f) << 24 | b[1] << 16 | b[2] << 8 | b[3];
return seed % maxNumber;
}
Run Code Online (Sandbox Code Playgroud)
maxNumber在这种情况下是独家的,这也是Random.Next(maxNumber)有效的.
编辑
来自@Servy的评论非常有趣,并引导我阅读了一篇名为"来自CryptoRandom的故事"的Stephen Toub和Shawn Farkas在2007年9月的MSDN杂志上发表的文章,可在此处下载,其中有一个使用RNGCryptoServiceProvider重新实现Random的示例这有偏见的解决方法.我在这里已经包含了它们的实现,因为源代码的格式非常讨厌,但是文章值得阅读它背后的原因.
public class CryptoRandom : Random
{
private RNGCryptoServiceProvider _rng = new RNGCryptoServiceProvider();
private byte[] _uint32Buffer = new byte[4];
public CryptoRandom() { }
public CryptoRandom(Int32 ignoredSeed) { }
public override Int32 Next()
{
_rng.GetBytes(_uint32Buffer);
return BitConverter.ToInt32(_uint32Buffer, 0) & 0x7FFFFFFF;
}
public override Int32 Next(Int32 maxValue)
{
if (maxValue < 0) throw new ArgumentOutOfRangeException("maxValue");
return Next(0, maxValue);
}
public override Int32 Next(Int32 minValue, Int32 maxValue)
{
if (minValue > maxValue) throw new ArgumentOutOfRangeException("minValue");
if (minValue == maxValue) return minValue;
Int64 diff = maxValue - minValue;
while (true)
{
_rng.GetBytes(_uint32Buffer);
UInt32 rand = BitConverter.ToUInt32(_uint32Buffer, 0);
Int64 max = (1 + (Int64)UInt32.MaxValue);
Int64 remainder = max % diff;
if (rand < max - remainder)
{
return (Int32)(minValue + (rand % diff));
}
}
}
public override double NextDouble()
{
_rng.GetBytes(_uint32Buffer);
UInt32 rand = BitConverter.ToUInt32(_uint32Buffer, 0);
return rand / (1.0 + UInt32.MaxValue);
}
public override void NextBytes(byte[] buffer)
{
if (buffer == null) throw new ArgumentNullException("buffer");
_rng.GetBytes(buffer);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3654 次 |
| 最近记录: |