使用Java验证OpenSSL生成的RSA/PSS签名返回失败如何解决
你代码存在两处核心错误直接导致校验失败:
1. Signature API调用逻辑错误
Java Signature 类的标准工作流程是:
- 调用
update方法传入原始待校验的明文数据,内部会自动按指定算法完成哈希计算 - 调用
verify方法传入待校验的签名二进制内容完成校验
你原代码的逻辑完全错位:
- 没有传入原始的
data.bin,反而把预计算好的哈希值作为输入,相当于对哈希值又做了一次SHA1计算,和OpenSSL的计算逻辑完全不符 - 把预计算的哈希值传给了
verify方法,本该传入的签名内容sigToVerify完全没用到,不可能校验通过
2. PSS填充的盐长度配置错误
RSA-PSS填充要求盐长度必须和签名时的配置完全一致,OpenSSL pkeyutl 默认使用的盐长度计算公式为:RSA密钥模长(字节) - 哈希输出长度(字节) - 2。
以2048位RSA密钥为例,模长为256字节,SHA1输出长度为20字节,计算得到默认盐长度为256 - 20 - 2 = 234,你原代码填的32和实际签名用的盐长度不匹配,自然校验失败。
额外优化建议
你代码中用FileInputStream.available()读取整个文件的写法不可靠,该方法返回的是当前可读字节数的估计值,不是文件总长度,大文件场景下大概率读不全,建议直接用Files.readAllBytes(Paths.get(文件路径))这类JDK自带的工具方法读取完整文件内容。
如果需要完全对齐OpenSSL的分步操作(先算哈希再做校验),也可以把Signature算法换成NONEwithRSA/PSS,然后把预计算的data.bin.digest内容传给update,再调用verify(sigToVerify),和你现在的修正代码逻辑完全等价。
内容的提问来源于stack exchange,提问作者Anton Khudyakov
相关产品推荐
相关产品推荐

