移植Xilinx U-Boot RSA验签代码后验证失败,求排查修正
问题分析与修正方案
我来帮你梳理下可能导致RSA验签结果异常的几个关键问题,以及对应的修正步骤:
1. 签名的端序格式不匹配
OpenSSL生成的十六进制签名是大端序的字节流,但U-Boot的rsa_mod_exp_sw函数要求输入的签名是小端序的uint32数组(和公钥的modulus/rr格式完全一致)。你直接将签名作为uint8数组传入,必然会导致模幂运算结果错误。
修正方法:
把OpenSSL输出的十六进制签名转换成符合要求的uint32数组:
- 将十六进制签名字符串转为大端字节数组(比如
157eb60ad0c77427...转成0x15, 0x7e, 0xb6, 0x0a, 0xd0, 0xc7, 0x74, 0x27...) - 按4字节为一组,反转每组内的字节顺序,得到小端uint32元素。例如第一组
0x15,0x7e,0xb6,0x0a要转为0x0ab67e15,作为uint32数组的第一个元素 - 2048位签名对应64个uint32元素,确保转换后的数组长度和公钥的
len字段(64)完全一致
2. 签名包含ASN.1哈希前缀
OpenSSL的openssl dgst -sign命令生成的签名,并不是直接对SHA256哈希值进行RSA签名,而是对带ASN.1编码前缀的哈希值签名。而U-Boot的rsa_mod_exp_sw只是执行原始的RSA模幂运算,输出的结果是带ASN.1前缀的完整数据,不是纯SHA256哈希值。
验证与修正:
- 先验证签名的ASN.1结构:
你会看到类似输出,其中OCTET STRING部分就是你要的纯SHA256哈希:# 将十六进制签名转为DER格式文件,再解析ASN.1 echo "你的十六进制签名字符串" | xxd -r -p > sig.der openssl asn1parse -inform DER -in sig.der0:d=0 hl=4 l= 257 cons: SEQUENCE 4:d=1 hl=2 l= 13 cons: SEQUENCE 6:d=2 hl=2 l= 9 prim: OBJECT :sha256 17:d=2 hl=2 l= 0 prim: NULL 19:d=1 hl=4 l= 239 prim: OCTET STRING [HEX DUMP]:你的SHA256哈希值 - 两种修正路径:
- 解析输出结果:调用
rsa_mod_exp_sw得到小端uint32数组后,先转成大端字节流,再解析ASN.1结构提取OCTET STRING部分,和openssl dgst -sha256 a.txt的结果对比 - 生成纯哈希签名:如果想直接得到纯哈希结果,改用以下命令生成签名(跳过ASN.1前缀):
用这个签名转换为小端uint32数组后,调用# 先生成a.txt的SHA256哈希,再对纯哈希做RSA签名 openssl dgst -sha256 a.txt | cut -d' ' -f2 | xxd -r -p > hash.bin openssl rsautl -sign -inkey key.pem -raw -in hash.bin -out sig.raw # 转成十六进制查看 xxd -p sig.rawrsa_mod_exp_sw得到的结果就是纯SHA256哈希的小端uint32数组,转成大端字节流后和原哈希一致。
- 解析输出结果:调用
3. 公钥与签名的配对验证
确保你用dumppublickey生成的U-Boot格式公钥,和用来签名的私钥是配对的:
# 从私钥导出OpenSSL格式公钥 openssl rsa -in key.pem -pubout -out pub.pem # 用dumppublickey重新处理这个公钥,对比生成的modulus、n0inv等字段和你当前使用的是否一致 dumppublickey pub.pem
如果字段不一致,说明公钥生成过程有误,会直接导致验签失败。
4. 输出结果的格式转换
rsa_mod_exp_sw的输出是小端序的uint32数组,你需要将其转换为大端字节流后再进行对比:
- 遍历输出的uint32数组,每个元素按大端字节序拆分(比如
0x0ab67e15拆成0x0a, 0xb6, 0x7e, 0x15) - 拼接所有字节得到完整的大端字节流,再和目标哈希(或ASN.1结构)对比
内容的提问来源于stack exchange,提问作者xutao
相关产品推荐
相关产品推荐

