我想安全地生成一個範圍[0,N)的隨機數,其中N是一個參數。但是,System.Security.Cryptography.RandomNumberGenerator只提供一個GetBytes()方法來填充具有隨機值的數組。安全地生成一致隨機的BigInteger
(我需要在SRP稍加修改的版本中使用隨機數的隨機整數。「稍微修改」部分是在我的掌握,唯一的原因,我甚至感動加密的東西。)
我已經寫了一個方法來做到這一點,但我正在尋找更好的方法,或者至少確認我做得對。
using System.Numerics
///<summary>Generates a uniformly random integer in the range [0, bound).</summary>
public static BigInteger RandomIntegerBelow(this System.Security.Cryptography.RandomNumberGenerator source, BigInteger bound) {
Contract.Requires<ArgumentException>(source != null);
Contract.Requires<ArgumentException>(bound > 0);
Contract.Ensures(Contract.Result<BigInteger>() >= 0);
Contract.Ensures(Contract.Result<BigInteger>() < bound);
//Get a byte buffer capable of holding any value below the bound
var buffer = (bound << 16).ToByteArray(); // << 16 adds two bytes, which decrease the chance of a retry later on
//Compute where the last partial fragment starts, in order to retry if we end up in it
var generatedValueBound = BigInteger.One << (buffer.Length * 8 - 1); //-1 accounts for the sign bit
Contract.Assert(generatedValueBound >= bound);
var validityBound = generatedValueBound - generatedValueBound % bound;
Contract.Assert(validityBound >= bound);
while (true) {
//generate a uniformly random value in [0, 2^(buffer.Length * 8 - 1))
source.GetBytes(buffer);
buffer[buffer.Length - 1] &= 0x7F; //force sign bit to positive
var r = new BigInteger(buffer);
//return unless in the partial fragment
if (r >= validityBound) continue;
return r % bound;
}
}
這是一些漂亮的代碼。 – Amy 2011-03-16 19:56:49