c++ - 要求编译器发出无分支/恒定时间代码
问题描述
在密码学中,任何依赖于秘密数据(例如私钥)的代码都必须在恒定时间内执行,以避免侧信道定时攻击。
目前最流行的架构(x86-64 和 ARM AArch64)都支持某些类型的条件执行指令,例如:
即使这样的指令不可用,也有一些技术可以将一段代码转换为无分支版本。性能可能会受到影响,但在这种情况下,它不是主要目标——在恒定时间内运行才是。
因此,原则上应该可以在例如 C/C++ 中编写无分支代码,并且确实可以看出 gcc/clang 经常会在优化打开的情况下发出无分支代码(gcc 中甚至有一个特定的标志:)-fif-conversion2
。然而,这似乎是一个优化决策,如果编译器认为无分支会执行更差(例如,如果“then”和“else”子句执行大量计算,超过在错误预测的分支),那么我假设编译器会发出常规代码。
如果恒定时间是一个不可协商的目标,则可能会被迫使用上述一些技巧来生成无分支代码,从而使代码变得不那么清晰。此外,性能通常是次要且非常重要的目标,因此开发人员必须希望编译器能够推断出无分支代码背后的预期操作并发出有效的指令序列,通常使用上述指令。这可能需要在查看汇编输出时一遍又一遍地重写代码,直到一个神奇的咒语满足编译器——这可能会因编译器而异,或者当新版本出现时。
总的来说,这对双方来说都是一个可怕的情况:编译器编写者必须从混淆代码中推断出意图,将其转换为更简单的指令序列;虽然开发人员必须编写这样的混淆代码,因为不能保证简单、清晰的代码实际上会在恒定时间内运行。
将其变成一个问题:如果必须在恒定时间内(或根本不)发出某段代码,是否有编译器标志或编译指示会强制代码如此发出,即使编译器预测会更糟性能优于分支版本,或者如果不可能,则中止编译?开发人员可以放心地编写清晰的代码,因为它是恒定时间的,同时为编译器提供清晰且易于分析的代码。我知道这可能是一个依赖于语言和编译器的问题,所以无论是 gcc 还是 clang,我都会对 C 或 C++ 答案感到满意。
解决方案
推荐阅读
- php - MySQL查询以在表的任何字段中查找完全匹配
- javascript - 'yield' 表达式隐含地导致一个 'any' 类型,因为它的包含生成器缺少返回类型注释
- javascript - 我只想滚动 1 个 div 元素,但 css 溢出:自动不起作用
- php - 不可见验证码正常时的 HTML 提交按钮
- reactjs - 在上传到 Firebase 之前在 React 上调整图像文件的大小
- powershell - 如何获取 AZCopy 的命令行?
- php - php move-uploaded-file 将地址设置为文件名
- oracle - 使用 Visual Studio 2017 连接到 Oracle DB
- recursion - RISC-V 中的递归程序(过程调用)
- linux - 如何隐藏 nginx.conf 授权凭据?