【问题标题】:Is masking effective for thwarting side channel attacks?掩蔽对于阻止侧信道攻击是否有效?
【发布时间】:2015-03-08 02:14:35
【问题描述】:

我正在使用一些 bigint 公钥加密代码。使用按位掩码来确保计算时序和访问的内存地址与数据值无关是否安全?

这种技术是否容易受到基于指令时序、功率、射频发射或其他我不知道的因素的侧信道攻击? (作为参考,我知道 RSA 致盲、EC 蒙哥马利阶梯、缓存刷新等技术。)


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

uint a = (...), b = (...);
if (a < b)
    a += b;

现在翻译为使用常量时间掩码:

uint a = (...), b = (...);
uint mask = -(uint)(a < b);
a = ((a + b) & mask) | (a & ~mask);

注意a &lt; b为0或1,掩码为0x00000000或0xFFFFFFFF。


同样,对于高级操作 (C++):

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

【问题讨论】:

标签: c++ c cryptography constant-time


【解决方案1】:

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

特别是,让我们看一下您的第一个示例:

uint a = (...), b = (...);
uint mask = -(uint)(a < b);
a = ((a + b) & mask) | (a & ~mask);

我看到了两种可能无法在恒定时间内运行的看似合理的方式:

  1. 比较 a &lt; b 可能需要也可能不需要固定时间,具体取决于编译器(和 CPU)。如果它被编译为简单的位操作,它可能是常数时间;如果它被编译为使用条件跳转,那很可能不是。

  2. 在高优化级别上,过于聪明的编译器可能会检测到正在发生的事情(例如,通过根据比较将代码分成两条路径,并在合并它们之前分别优化它们)并将其“优化”回来进入我们试图避免的非常量时间码。

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

避免第一个问题的一种可能方法是将比较替换为显式位操作,如下所示:

uint32_t a = (...), b = (...);
uint32_t mask = -((a - b) >> 31);
a = ((a + b) & mask) | (a & ~mask);

但是,请注意,如果我们可以确定 ab 相差小于 231,则这仅等同于您的原始代码。如果不能保证,我们必须在减法之前将变量转换为更长的类型,例如:

uint32_t mask = (uint32_t)(( (uint64_t)a - (uint64_t)b ) >> 32);

话虽如此,即使这也不是万无一失的,因为编译器仍然可以决定将此代码转换为非恒定时间的东西。 (例如,在 32 位 CPU 上进行 64 位减法可能会花费可变时间,具体取决于是否存在借位——这正是我们在这里试图隐藏的内容。)

一般而言,确保不会发生此类时序泄漏的唯一方法是:

  1. 手动检查生成的汇编代码(例如,在您没有预料到的地方寻找跳转指令),并且

  2. 实际上对代码进行基准测试,以验证它确实需要相同的时间来运行,而不管输入如何。

显然,您还需要为您希望支持的编译器和目标平台的每个组合单独执行此操作。

【讨论】:

  • 编译器实际上可以利用 ARM 的conditional execution 等特性将原始版本编译为常量时间。但你是对的,检查生成的汇编代码以了解实际情况很重要。
【解决方案2】:

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

作为一般经验法则,请使用众所周知的加密库,因为它们应该能够抵御侧信道攻击。如果做不到这一点,您通常可以转换信息,对其进行处理,然后再转换回结果。这对于公钥加密特别有效,因为它通常是同态的。

【讨论】:

  • 关于反向变换的好信息,这当然是一个很好的技术。
猜你喜欢
  • 1970-01-01
  • 2021-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-15
  • 1970-01-01
  • 2018-09-25
  • 2015-11-10
相关资源
最近更新 更多