【问题标题】:Cryptographically secure random integer between two values两个值之间的加密安全随机整数
【发布时间】:2020-07-13 10:18:43
【问题描述】:

我一直在使用RNGCryptoServiceProvider 创建一个随机整数。这将在整数的上下限之间生成一个随机整数。

private static RNGCryptoServiceProvider rngCryptoServiceProvider = new RNGCryptoServiceProvider();

public int Execute(int lowerBound, int upperBound)
{
    // initialize an array of bytes equal to the number of bytes in an integer
    var numberOfBytes = sizeof(int);
    var bytes = new byte[numberOfBytes];

    // fill the array with random bytes
    rngCryptoServiceProvider.GetBytes(bytes);

    // convert the byte array to an integer
    var bitsAsInteger = BitConverter.ToInt32(bytes, 0);
    
    return bitsAsInteger;
}

现在我想在两个整数之间生成一个随机整数。根据我的阅读,这不是一项微不足道的任务。所以,我想我可以随机播种System.Random 类并使用Next() 功能来进行数学运算。这是一个明智的做法吗?

private static RNGCryptoServiceProvider rngCryptoServiceProvider = new RNGCryptoServiceProvider();

public int Execute(int lowerBound, int upperBound)
{
    // initialize an array of bytes equal to the number of bytes in an integer
    var numberOfBytes = sizeof(int);
    var bytes = new byte[numberOfBytes];

    // fill the array with random bytes
    rngCryptoServiceProvider.GetBytes(bytes);

    // convert the byte array to an integer
    var bitsAsInteger = BitConverter.ToInt32(bytes, 0);

    // use the random integer to seed the non cryptographically secure Random class
    var random = new System.Random(bitsAsInteger);
    
    // use the Next() functionality to do the math to get a random number between two values
    var randomInteger = random.Next(lowerBound, upperBound);
    
    return randomInteger;
}

有没有其他方法可以在不使用System.Random 的情况下达到相同的结果?

【问题讨论】:

    标签: c# random


    【解决方案1】:

    你可以使用模数。

    private static RNGCryptoServiceProvider rngCryptoServiceProvider = new RNGCryptoServiceProvider();
    
    public int Execute(int lowerBound, int upperBound)
    {
        // initialize an array of bytes equal to the number of bytes in an integer
        var numberOfBytes = sizeof(int);
        var bytes = new byte[numberOfBytes];
    
        // fill the array with random bytes
        rngCryptoServiceProvider.GetBytes(bytes);
    
        // convert the byte array to an integer
        var bitsAsInteger = BitConverter.ToInt32(bytes, 0);
        var m = (int)(Math.Abs(bitsAsInteger) % ((long)int.MaxValue - int.MinValue));
        return m + lowerBound;
    }
    

    【讨论】:

    • 你能解释一下为什么使用 Math.Abs​​ 吗?如果界限足够大,我不确定这是否可行。如果上限是 int.Max 而下限是 int.Min 那么我们会溢出吗?
    • 选择,但即使是 Math.Mod 在大多数情况下也会引入偏差。粗略地说,您需要忽略剩菜的价值。例如,如果你想要一个 90 到 180 之间的数字,从一个字节,那么你 (mod 90),但 90 只进入 256 两次,剩下 76。所以如果随机字节大于等于180,就应该丢弃重试。
    • 我使用 ABS 是因为我想生成数字 0 来区分。在 C# 中,模运算符实际上是一个提醒运算符,例如 -5 % 3 = -2 但它应该是 1。因为,溢出你是对的。我将其更改为 long on code。 @Todd 是对的。
    猜你喜欢
    • 2018-09-18
    • 2015-01-22
    • 2012-04-25
    • 2015-11-07
    • 2015-02-12
    • 2013-10-14
    • 1970-01-01
    • 2011-09-26
    • 2015-09-09
    相关资源
    最近更新 更多