RSA签名故障分析
基于CRT的签名过程
标准RSA签名算法使用公式:s=m^d (mod n),其中s代表签名,m为消息,d是私钥指数,n为公钥。为提高大数运算效率,密码库常采用中国剩余定理(CRT)将单次大计算拆分为两个较小运算。
首先计算dp=d (mod (p-1))和dq=d (mod (q-1)),然后分别计算两个部分签名:
- s1 = m^dp (mod p)
- s2 = m^dq (mod q)
最后通过组合公式s=(s1qqInv)+(s2ppInv) (mod n)生成最终签名。
故障攻击原理
当两个部分签名之一(假设使用q计算的s2)出现错误时,会产生故障签名。虽然正确签名可通过s^e (mod n)验证与原始消息匹配,但故障签名会使s^e (mod q) ≠ m。
此时攻击者可计算n与s^e-m的最大公约数来提取p。由于n=p*q,通过n/p即可获得q,从而完整获取私钥。
玩具程序故障测试
通过C语言编写简易RSA-CRT签名程序(无填充和校验),使用调试器手动修改部分签名制造故障。Python程序利用故障签名成功计算私钥并解密加密消息。测试通过改变签名过程不同阶段的数据,验证私钥提取的可行性。
基于Manticore的比特翻转
使用Binary Ninja分析程序反汇编代码,定位目标数据内存地址。通过Manticore脚本遍历内存字节,逐位翻转指令后执行签名程序。对非崩溃/超时的执行结果尝试私钥提取,并通过解密验证准确性。最终生成包含部分签名、私钥及准确性的CSV结果文件。
实验结果
938次比特翻转测试中:
- 45次(4.8%)成功获取正确私钥
- 近55%导致程序崩溃或超时
- 约31%未改变部分签名
自动化方法大幅加速漏洞利用开发,只需向Manticore描述漏洞即可获得完整的利用方案列表,特别适用于不精确故障(如Rowhammer)场景下的比特簇分析。
mbed TLS攻击实践
选择主要用于嵌入式系统的mbed TLS密码库,分析其PKCS#1 v1.5确定性填充方案。通过调试器定位目标数据时发现运行时校验机制会阻止故障签名生成,需跳过两个关键检查才能产生有效故障签名。
攻击自动化实现
改用GDB脚本替代Manticore进行自动化攻击,通过比特翻转绕过两个校验检查。Python循环遍历内存字节,调用脚本诱导故障并提取私钥,结果写入CSV文件。
实际库测试结果
566次比特翻转测试(集中在签名执行代码段)结合两个校验绕过翻转:
- 28次(近5%)成功泄露私钥
- 约55%未能生成签名
结论
本研究证实故障攻击对真实程序的有效性,通过工具链实现从漏洞描述到完整利用方案的自动化生成。虽然未能在真实环境中完成测试,但为未来研究开辟了新的可能性。