Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.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++_C_Cryptography_Constant Time - Fatal编程技术网

C++ 掩蔽对挫败侧通道攻击有效吗?

C++ 掩蔽对挫败侧通道攻击有效吗?,c++,c,cryptography,constant-time,C++,C,Cryptography,Constant Time,我正在使用一些bigint公钥密码。使用位屏蔽以确保访问的计算定时和内存地址独立于数据值是否安全 这种技术是否容易受到基于指令定时、功率、射频发射或其他我不知道的因素的侧通道攻击?(作为参考,我了解RSA致盲、EC Montgomery梯形图、缓存刷新等技术。) 简单代码示例(C/C++): 以下是可接受的安全翻译吗 Integer x = (...); uint mask = -(uint)x.isFoo(); // Assume this is constant-time Integer

我正在使用一些bigint公钥密码。使用位屏蔽以确保访问的计算定时和内存地址独立于数据值是否安全

这种技术是否容易受到基于指令定时、功率、射频发射或其他我不知道的因素的侧通道攻击?(作为参考,我了解RSA致盲、EC Montgomery梯形图、缓存刷新等技术。)


简单代码示例(C/C++):

以下是可接受的安全翻译吗

Integer x = (...);
uint mask = -(uint)x.isFoo();  // Assume this is constant-time
Integer y(x);                  // Copy constructor
y.doBar();                     // Assume this is constant-time
x.replace(y, mask);            // Assume this uses masking

在代码中使用掩蔽或其他技术可能很粗略,因为编译器会执行各种您通常不知道的优化。您在原始帖子中提到的一些方法要好得多

一般的经验法则是使用众所周知的加密库,因为它们应该被加固以抵御侧通道攻击。如果失败,您通常可以转换信息,对其进行处理,然后转换回结果。这在公钥密码体制中尤其有效,因为它通常是同态的。

这种技术可能是安全的。。。如果我们假设需要恒定时间的操作真的执行,并且如果编译器没有更改代码来执行其他操作

特别是,让我们来看看你的第一个例子:

uint a=(…),b=(…);
uint掩码=-(uint)(a
我发现有两种似乎合理的方法可能无法在恒定时间内运行:

  • 比较
    a
    可能需要也可能不需要固定的时间,这取决于编译器(和CPU)。如果它被编译成简单的位操作,它可能是常数时间;如果它被编译为使用条件跳转,则很可能不是

  • 在高优化级别上,一个过于聪明的编译器可能会检测到正在发生的事情(比如,根据比较将代码拆分为两条路径,并在将它们合并回来之前分别对它们进行优化),然后将其“优化”回到我们试图避免的非恒定时间代码中

    (当然,一个足够聪明的编译器也有可能将天真、看似非恒定时间的代码优化为恒定时间操作,如果它认为这样更有效的话!)

  • 避免第一个问题的一种可能方法是用显式位操作代替比较,如:

    uint32_t a=(…),b=(…);
    uint32_t mask=-((a-b)>>31);
    a=((a+b)和掩码)|(a和掩码);
    
    但是,请注意,如果我们可以确保
    a
    b
    之间的差异小于231,则这仅等同于您的原始代码。如果不能保证,我们必须在减法之前将变量转换为更长的类型,例如:

    uint32-t掩码=(uint32-t)((uint64-t)a-(uint64-t)b>>32);
    
    尽管如此,即使这样也不是万无一失的,因为编译器仍然可以决定将此代码转换为非恒定时间的代码。(例如,32位CPU上的64位减法可能需要不同的时间,具体取决于是否存在借用,这正是我们试图隐藏的内容。)

    通常,确保不发生此类正时泄漏的唯一方法是:

  • 手动检查生成的汇编代码(例如,在您没有预料到的地方查找跳转指令),以及

  • 实际上,对代码进行基准测试,以验证无论输入如何,它确实需要相同的时间运行


  • 显然,对于您希望支持的编译器和目标平台的每个组合,您也需要分别执行此操作。

    乍一看,它看起来不错,您是否在
    -o
    的高设置下测试过它?请注意,doBar当然不会有副作用,因为现在如果
    isFoo
    返回true或false,就会调用它。背景动机:编译器实际上可以利用ARM等功能将原始版本编译为常量时间。但是你是对的,检查生成的汇编代码以了解实际情况是很重要的。关于反向转换的好信息,这当然是一种很好的使用技术。
    uint a = (...), b = (...);
    uint mask = -(uint)(a < b);
    a = ((a + b) & mask) | (a & ~mask);
    
    Integer x = (...);
    if (x.isFoo())
        x.doBar();
    
    Integer x = (...);
    uint mask = -(uint)x.isFoo();  // Assume this is constant-time
    Integer y(x);                  // Copy constructor
    y.doBar();                     // Assume this is constant-time
    x.replace(y, mask);            // Assume this uses masking