c# – 如何使用RNGCryptoServiceProvider根据我的首选字符创建随机密码?

前端之家收集整理的这篇文章主要介绍了c# – 如何使用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);
    }

一些可能的问题?这是一个静态函数,有一些奇怪的种子模式可能不安全,仍然使用System.Random().

使用上面的随机生成器,我以这种低效的方式创建一个字符串:

validCharacters = "abcdefghjkmnoxyz023456789#!@";

然后使用有效数组循环并获取“createPassword(length)”类型字符串(注意使用不包含容错字符的字符集,如1 i等).

这是如何做到的,还是有更简单,更安全,更有效的方式?

解决方法

为了生成随机数,您可以返回种子的剩余部分除以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;
}

在这种情况下,maxNumber是独占的,这也是Random.Next(maxNumber)的工作原理.

编辑

来自@Servy的评论非常有趣,并引导我阅读2007年9月MSDN杂志上发表的题为“来自CryptoRandom的故事”的Stephen Toub和Shawn Farkas的一篇文章,可以下载here,其中有一个使用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);
    }
}

猜你在找的C#相关文章