你无法预知未来
从根本上讲,你无法预测任何语言中未来的优化器可能会或不会做什么。
为了展望未来,最好的方法是操作系统本身提供定时常量测试,这样它们可以在所有环境中得到适当的测试和使用。
这已经持续了相当长的时间。例如,libc中的timingsafe_bcmp()函数首次出现在OpenBSD 4.9中(发布于2011年5月)。
显然,编程环境需要采用这些方法并/或提供自己的函数,以确保它们不会被优化掉。
检查汇编代码
有一些关于优化器的讨论here。虽然它是针对C(和C++)的,但它实际上是与语言无关的,你只能看看当前优化器能做什么,而不能预测未来的优化器会做什么。
无论如何,他们正确地建议检查汇编代码以了解你的优化器的工作方式。
对于Java来说,由于其性质,这并不像C或C++那样“容易”,但对于特定的安全功能来说,为当前环境实际执行这些操作应该并不是不可能的。
可能可以避免
您可以尝试避免时序攻击。
E.g.:
尽管直觉上添加随机时间似乎是正确的做法,但它不起作用:攻击者已经在时序攻击中使用统计分析,你只是增加了更多噪音。
https://security.stackexchange.com/questions/96489/can-i-prevent-timing-attacks-with-random-delays
尽管如此:如果您的应用程序足够慢,即等待足够长的时间,那么您仍然可以实现时间常数实现。例如:您可以等待计时器触发,然后才继续处理比较结果,从而避免时序攻击。
检测
使用时间常数比较的实现,应该可以将时序攻击漏洞的检测编写到应用程序中。
例如:
- 在初始化期间运行某些测试
- 作为正常操作的一部分定期运行相同的测试。
优化器可能会很棘手,因为它甚至可以改变执行顺序。但是,例如使用程序中没有的输入(例如外部文件),并运行两次:一次进行正常比较和相同的字符串,一次使用完全不同的字符串(例如异或)然后再次使用这些输入进行常数时间比较。现在您有4个时间:正常比较不应该相同,常数时间比较应该更慢且相同。如果失败:警告用户/应用程序维护者,常数时间的东西在生产使用中可能已经损坏。
一个理论的选项是自己收集实际的计时数据(同时记录失败/成功),并进行统计分析。但实际操作起来会很棘手,因为你的测量需要非常准确,而且不能进行数百万次循环,你只能处理一个比较,并且没有足够的分辨率来进行足够精确的测量...。
int
将导致与概率为2**-32
,即2.3e-10
的冲突,这对于任何安全敏感的东西来说都太多了。你会将猜测秘密(像2**-256
,即不可能的机会)降低到猜测碰撞。 +++ 使用long
将更好(并且在 64 位 JVM 上也是恒定时间),但仍然不够好。 - maaartinus