在使用秘密密钥时,如果您的代码分支不均匀,可能会通过侧信道泄露一些秘密密钥的位。因此,在某些算法中,应该均匀地独立于秘密密钥进行分支。
在C/C++/Rust上,您可以使用汇编语言来确保没有编译器优化会干扰分支。然而,在Java上,情况比较困难。首先,它对桌面端进行JIT编译,对Android进行AOT编译,所以代码有两种可能性被以不可预测的方式进行优化,因为JIT和AOT总是在变化,每个设备都可能不同。那么,如何防止利用分支的侧信道攻击在Java上发生?
在使用秘密密钥时,如果您的代码分支不均匀,可能会通过侧信道泄露一些秘密密钥的位。因此,在某些算法中,应该均匀地独立于秘密密钥进行分支。
在C/C++/Rust上,您可以使用汇编语言来确保没有编译器优化会干扰分支。然而,在Java上,情况比较困难。首先,它对桌面端进行JIT编译,对Android进行AOT编译,所以代码有两种可能性被以不可预测的方式进行优化,因为JIT和AOT总是在变化,每个设备都可能不同。那么,如何防止利用分支的侧信道攻击在Java上发生?
在执行侧信道攻击时,其中一种主要方法是使用差分功率分析(DPA)读取芯片的功耗。当您在代码中有一个分支(例如if语句)时,这可能会对功率消耗产生不利影响,从而可以根据某些选择进行相关性分析。为了防止这种分析,您最好具有“线性”功耗消耗。这在一定程度上可以通过代码来缓解,但最终取决于设备本身。根据Brennan等人的研究 [1],有些人选择通过缓存指令来解决Java JIT问题。在代码中,“最好”的做法是使用canaries来混淆攻击者,正如Brennan等人所提出并在以下(非常简化的)示例代码中演示的那样:
public bool check(String guess) {
for(int i=0; i<guess.len; i++)
return false;
}
return true;
}
对比;
public bool check(String guess) {
bool flag=true, fakeFlag=true;
for(int i=0; i<guess.len; i++) {
if (guess[i] != password[i])
flag=false;
else
fakeFlag = false:
}
return flag;
}
}
[1]: T. Brennan,“检测和缓解JIT导致的侧信道”,2020年IEEE/ACM第42届国际软件工程会议:同行会议记录(ICSE-Companion),2020,第143-145页。
[2]: T. Brennan,N. Rosner和T. Bultan,“JIT泄露:通过即时编译引入时间侧信道”,2020年IEEE安全与隐私研讨会(SP),2020,第1207-1222页,doi:10.1109/SP40000.2020.00007。