Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Random.Next()可以从其输出预测吗_C#_.net_Security_Random - Fatal编程技术网

C# Random.Next()可以从其输出预测吗

C# Random.Next()可以从其输出预测吗,c#,.net,security,random,C#,.net,Security,Random,拥有这个(简化的)C类: 通过查看此方法生成的值,是否可以预测GetRandomValue()的下一个值 假设(为了回答问题): 攻击者不知道种子(当然) 攻击者可以观察到无限数量的GetRandomValue()的后续结果 我这样问是因为我看到一些代码使用类似的方法来生成某种访问令牌。这段代码不是我写的,我可能会使用.NET的一个加密随机类。我只是好奇这是否仍然足够安全。根据肯尼特的评论,我创建了一个关于如何“打破”随机性的概念证明。边缘可能有点粗糙,但它表明您只需要55个值来预测下一个(

拥有这个(简化的)C类:

通过查看此方法生成的值,是否可以预测
GetRandomValue()
的下一个值

假设(为了回答问题):

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

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

根据肯尼特的评论,我创建了一个关于如何“打破”
随机性的概念证明。边缘可能有点粗糙,但它表明您只需要55个值来预测下一个(以及之后的每个值)

下面的代码首先从单个
随机
实例中读取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;
    }
}
公共类程序
{
静态void Main(字符串[]参数)
{
const int INTERNAL_ARRAY_SIZE=56;
const int inxtp_START=21;
var internalArray=new int[内部数组大小];
var random=新的random();
//读取56个值。
对于(int x=0;x<内部数组大小-1;x++)
{
internalArray[x+1]=random.Next();
}
int inext=内部数组大小-1;
int inxtp=inxtp\u启动;
//预测接下来的10个值。
对于(int x=0;x<10;x++)
{
int predictedRandomValue=PredictNextRandomValue(internalArray,ref-inxt,ref-inxtp);
int officialRandomValue=random.Next();
if(officialRandomValue==predictedRandomValue)
{
WriteLine(“是的,它们是一样的。”);
}
其他的
{
WriteLine(“不,它们不同。”);
}
}
}
私有静态int PredictNextRandomValue(int[]种子数组,ref int inxt,ref int inxtp)
{
const int MBIG=int.MaxValue;
内部检索;
int locINext=不精确;
int locinxtp=inxtp;
如果(++locINext>=56)locINext=1;
如果(++locINextp>=56)locINextp=1;
retVal=seedArray[locINext]-seedArray[locINextp];
如果(retVal==MBIG)retVal--;
如果(retVal<0)retVal+=MBIG;
seedArray[locinquet]=retVal;
不精确=不精确;
inxtp=locinxtp;
返回返回;
}
}

在对某人的评论中,讨论了使用所讨论的概念来攻击
系统。随机
。我认为观察57个值就足以预测其余值。
系统。随机
从来都不是为了密码安全而设计的。事实上,它是为决定论而设计的。通常情况下,您希望能够生成可重复的随机数流。对于您想要使用的安全随机数,不,它不是加密安全的——它不是设计为加密安全的。加密安全的PRNG需要做更多的工作,因此运行速度较慢。它必须尽可能地收集熵/随机性,并且必须频繁地为自己重新设定种子。它还在内部使用加密过程,这再次降低了它的速度。请参阅CSPRNG的示例。答案是一个聪明的解决方案,但您也可以尝试所有20亿颗种子。需要几分钟。这适用于任何带有小种子的生成器。PredictNextRandomValue在哪里定义?@BillSambrone-如果向下滚动,下面有一个函数。或者你指的是别的什么?
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;
    }
}