web-dev-qa-db-ja.com

範囲内で暗号的に安全なランダム整数を生成するにはどうすればよいですか?

パスワードを生成するプログラムに対して、指定された範囲内で均一で安全なランダム整数を生成する必要があります。今私はこれを使用しています:

RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] Rand = new byte[4];
rng.GetBytes(Rand);
int i = BitConverter.ToUInt16(Rand, 0);
int result = i%max;   //max is the range's upper bound (the lower is 0)

この方法は暗号化の目的で安全に使用できますか?そうでない場合は、どうすればよいですか?

10
Hey

https://Gist.github.com/1017834 から取得したCryptoRandomクラスを見ることができます。これは、StephenToubとShawnFarkasによるオリジナルバージョンです。このクラスでは、暗号的に安全であると思われるいくつかのランダムジェネレーターを実装します。

私のプロジェクトでは、ランダムなint生成のために次のバージョンを使用しました。

public class RandomGenerator
{
    readonly RNGCryptoServiceProvider csp;

    public RandomGenerator()
    {
        csp = new RNGCryptoServiceProvider();
    }

    public int Next(int minValue, int maxExclusiveValue)
    {
        if (minValue >= maxExclusiveValue)
            throw new ArgumentOutOfRangeException("minValue must be lower than maxExclusiveValue");

        long diff = (long)maxExclusiveValue - minValue;
        long upperBound = uint.MaxValue / diff * diff;

        uint ui;
        do
        {
            ui = GetRandomUInt();
        } while (ui >= upperBound);
        return (int)(minValue + (ui % diff));
    }

    private uint GetRandomUInt()
    {
        var randomBytes = GenerateRandomBytes(sizeof(uint));
        return BitConverter.ToUInt32(randomBytes, 0);
    }

    private byte[] GenerateRandomBytes(int bytesNumber)
    {
        byte[] buffer = new byte[bytesNumber];
        csp.GetBytes(buffer);
        return buffer;
    }
}
9
afonte