可以从Random.Next()的输出中预测它吗?

本文关键字:输出 Random Next | 更新日期: 2023-09-27 18:03:36

有了这个(简化的)c#类:

public static class RandomValue
{
    private static readonly Random s_random = new Random();
    public static int GetRandomValue()
    {
        lock (s_random)
        {
            return s_random.Next();
        }
    }
}

是否有可能通过查看该方法生成的值来预测GetRandomValue()的下一个值?

假设(为了问题的缘故):

  • 攻击者不知道种子(当然)。
  • 攻击者可以观察到GetRandomValue()的无限次后续结果。

我问这个问题是因为我看到一些代码使用类似的方法来生成某种访问令牌。这段代码不是我写的,我可能会使用。net的加密随机类。我只是好奇这是否仍然足够安全。

可以从Random.Next()的输出中预测它吗?

根据kennytm的评论,我创建了一个关于如何"打破"Random的概念证明。这可能有点粗糙,但它表明你只需要55个值来预测下一个(以及之后的每个值)。

下面的代码首先从单个Random实例读取55个值,然后预测接下来的10个值:

public class Program
{
    static void Main(string[] args)
    {
        const int INTERNAL_ARRAY_SIZE = 56;
        const int INEXTP_START = 21;
        var internalArray = new int[INTERNAL_ARRAY_SIZE];
        var random = new Random();
        // Read 56 values.
        for (int x = 0; x < INTERNAL_ARRAY_SIZE - 1; x++)
        {
            internalArray[x + 1] =  random.Next();
        }
        int inext = INTERNAL_ARRAY_SIZE - 1;
        int inextp = INEXTP_START;
        // Predict the next 10 values.
        for (int x = 0; x < 10; x++)
        {
            int predictedRandomValue = PredictNextRandomValue(internalArray, ref inext, ref inextp);
            int officialRandomValue = random.Next();
            if (officialRandomValue == predictedRandomValue)
            {
                Console.WriteLine("Yes, they're the same.");
            }
            else
            {
                Console.WriteLine("No, they're different.");
            }
        }
    }
    private static int PredictNextRandomValue(int[] seedArray, ref int inext, ref int inextp)
    {
        const int MBIG =  int.MaxValue;
        int retVal;
        int locINext = inext;
        int locINextp = inextp;
        if (++locINext >= 56) locINext = 1;
        if (++locINextp >= 56) locINextp = 1;
        retVal = seedArray[locINext] - seedArray[locINextp];
        if (retVal == MBIG) retVal--;
        if (retVal < 0) retVal += MBIG;
        seedArray[locINext] = retVal;
        inext = locINext;
        inextp = locINextp;
        return retVal;
    }
}