【发布时间】:2011-03-16 19:43:37
【问题描述】:
我想在 [0, N) 范围内安全地生成一个随机数,其中 N 是一个参数。但是,System.Security.Cryptography.RandomNumberGenerator 只提供了一个 GetBytes() 方法来用随机值填充数组。
(我需要在 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;
}
}
【问题讨论】:
标签: .net security random cryptography biginteger