Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.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# 安全的平等:为什么不平等仍然持续减少时间?_C#_.net_Optimization_C# 4.0_Timing - Fatal编程技术网

C# 安全的平等:为什么不平等仍然持续减少时间?

C# 安全的平等:为什么不平等仍然持续减少时间?,c#,.net,optimization,c#-4.0,timing,C#,.net,Optimization,C# 4.0,Timing,我有一个比较两个字节数组是否相等的方法,主要的警告是,它不会在检测到不相等时失败并提前退出。基本上,该代码用于比较跨站点请求伪造令牌,并(尽可能)避免使用计时破解密钥的能力。我希望我能找到详细讨论攻击的论文的链接,但重要的是,如果两个字节数组相等,我的代码仍然有统计上可测量的偏差,可以更快返回——尽管这是一个数量级更好。不用多说,下面是代码: public static bool SecureEquals(byte[] original, byte[] potential) { // T

我有一个比较两个字节数组是否相等的方法,主要的警告是,它不会在检测到不相等时失败并提前退出。基本上,该代码用于比较跨站点请求伪造令牌,并(尽可能)避免使用计时破解密钥的能力。我希望我能找到详细讨论攻击的论文的链接,但重要的是,如果两个字节数组相等,我的代码仍然有统计上可测量的偏差,可以更快返回——尽管这是一个数量级更好。不用多说,下面是代码:

public static bool SecureEquals(byte[] original, byte[] potential)
{
    // They should be the same size, but we don't want to throw an
    // exception if we are wrong.
    bool isEqual = original.Length == potential.Length;
    int maxLenth = Math.Max(original.Length, potential.Length);

    for(int i=0; i < maxLength; i++)
    {
        byte originalByte = (i < original.Length) ? original[i] : (byte)0;
        byte potentialByte = (i < potential.Length) ? potential[i] : (byte)0;

        isEqual = isEqual && (originalByte == potentialByte);
    }

    return isEqual;
}
公共静态bool SecureEquals(字节[]原始,字节[]潜在)
{
//它们应该是同样大小的,但我们不想扔一个
//如果我们错了,例外。
bool isEqual=原始.Length==潜在.Length;
int maxLenth=Math.Max(原始.Length,潜在.Length);
对于(int i=0;i
对于不相等令牌,相等令牌和不相等令牌之间的平均时间差始终缩短10-25ms(取决于垃圾收集周期)。这正是我想要避免的。如果相对计时是相等的,或者平均计时是基于跑步而交换的,我会很高兴。问题是,对于不相等的令牌,我们一直在运行较短的时间。相反,如果我们在第一个不相等的令牌上停止循环,我们可能会有多达80倍的时间差

虽然与典型的渴望回报相比,这种平等性检查是一个重大改进,但仍然不够好。本质上,我不希望平等或不平等的结果更快地返回。如果我能让结果进入垃圾收集周期可以掩盖任何一致性偏差的范围,我会很高兴

有人知道是什么导致了不平等性加速的时间偏差吗?起初,我认为是三元运算符返回对数组的访问权,如果数组大小不等,则返回常量。问题是,如果两个数组的大小相同,我仍然会得到这种偏差

注:根据要求,有关定时攻击的文章链接如下:

  • (官方文件,链接至以下博客帖子)
  • (谈论Java库中的失败)
  • (更一般,但不完整)
此线路可能导致以下问题:

isEqual = isEqual && (originalByte == potentialByte);
如果
isEquals
已为false,则不必计算
originalByte==potentialByte
子表达式。您不希望此处出现短路,因此将其更改为:

isEqual = isEqual & (originalByte == potentialByte);
编辑:请注意,您已经在有效地泄漏有关原始数据大小的信息-因为它将始终在一个恒定的时间内运行,直到
潜在
数组超过
原始
数组的大小,此时时间将增加。要避免这种情况可能很棘手。。。因此,我会选择“如果大小不合适,则抛出异常”的方法,该方法明确有效地承认了这一点

编辑:只需回顾一下我在评论中包含的想法:

// Let's assume you'll never really need more than this
private static readonly byte[] LargeJunkArray = new byte[1024 * 32];

public static bool SecureEquals(byte[] original, byte[] potential)
{
    // Reveal that the original array will never be more than 32K.
    // This is unlikely to be particularly useful.
    if (potential.Length > LargeJunkArray.Length)
    {
        return false;
    }
    byte[] copy = new byte[potential.Length];
    int bytesFromOriginal = Math.Min(original.Length, copy.Length);
    // Always copy the same amount of data
    Array.Copy(original, 0, copy, 0, bytesFromOriginal);
    Array.Copy(LargeJunkArray, 0, copy, bytesFromOriginal,
               copy.Length - bytesFromOriginal);

    bool isEqual = original.Length == potential.Length;
    for(int i=0; i < copy.Length; i++)
    {
        isEqual = isEqual & (copy[i] == potential[i]);
    }

    return isEqual;
}
//让我们假设你永远不会真正需要比这更多的东西
私有静态只读字节[]LargeJunkArray=新字节[1024*32];
公共静态bool SecureEquals(字节[]原始,字节[]潜在)
{
//显示原始阵列永远不会超过32K。
//这不太可能特别有用。
if(potential.Length>LargeJunkArray.Length)
{
返回false;
}
byte[]copy=新字节[potential.Length];
int bytesFromOriginal=Math.Min(original.Length,copy.Length);
//始终复制相同数量的数据
数组.Copy(original,0,Copy,0,bytesFromOriginal);
数组.Copy(LargeJunkArray,0,Copy,bytesFromOriginal,
副本。长度-字节(来自原件);
bool isEqual=原始.Length==潜在.Length;
for(int i=0;i

请注意,这假设
Array.Copy
从任何源复制相同数量的数据需要相同的时间-这很可能不是真的,基于CPU缓存…

如果.NET应该足够聪明,可以优化它,那么您是否尝试引入一个计数器变量来计算不相等字符的数量,并且仅当该数字为零时才返回true

public static bool SecureEquals(byte[] original, byte[] potential)
{
    // They should be the same size, but we don't want to throw an
    // exception if we are wrong.
    int maxLength = Math.Max(original.Length, potential.Length);
    int equals = maxLength - Math.Min(original.Length, potential.Length);

    for(int i=0; i < maxLength; i++)
    {
        byte originalByte = (i < original.Length) ? original[i] : (byte)0;
        byte potentialByte = (i < potential.Length) ? potential[i] : (byte)0;

        equals += originalByte != potentialByte ? 1 : 0;
    }

    return equals == 0;
}
公共静态bool SecureEquals(字节[]原始,字节[]潜在)
{
//它们应该是同样大小的,但我们不想扔一个
//如果我们错了,例外。
int maxLength=Math.Max(原始.Length,潜在.Length);
int=maxLength-Math.Min(original.Length,potential.Length);
对于(int i=0;i
我不知道是什么原因造成了这种差异——在这里使用探查器似乎是一个很好的工具。但我会考虑采用不同的方法。

在这种情况下,我要做的是在方法中构建一个计时器,这样当给定两个相等的键时,它可以测量自己的计时。(使用秒表类。)它应该计算成功计时的平均值和标准偏差,并将其隐藏在某个全局状态中。当你得到一个不相等的关键点时,你可以测量你花了多少时间来检测这个不相等的关键点,然后通过旋转一个紧密的循环来弥补这个差异,直到找到合适的时间为止