Java使用RSA公钥通过Signature验证数据始终返回false的原因及解决方案
返回false的根本原因
你的代码从运算逻辑、填充规则、接口用法三个层面都存在错误,所以永远返回false:
- 混淆了RSA公钥加密和RSA数字签名的核心逻辑:
RSA加密的作用是保证数据保密性,用公钥加密明文,运算后得到的是只能用私钥解密的密文;而SHA256withRSA签名的作用是做身份校验和完整性校验,生成签名时是用私钥对「明文的SHA256哈希值+签名专用填充标识」做运算,验证时用公钥把签名解密得到哈希值,再和本地计算的明文哈希对比是否一致。你现在把公钥加密得到的密文直接当做签名传给verify方法,签名类解密后得到的是原明文"a",和预期的SHA256哈希结构完全不匹配,自然校验失败。 - 填充规则不兼容:你调用
Cipher.getInstance("RSA")用的是JDK默认的加密类PKCS#1填充,和SHA256withRSA用的签名专用PKCS#1 v1.5填充格式完全不同,就算内容一致,填充部分也会导致校验失败。 - 接口用法错误:
Signature类的verify方法接收的是sign()方法生成的签名字节数组,不是Cipher类加密输出的密文字节数组,二者不能混用。
正确的实现方式
根据你的实际业务需求,选择对应方案即可:
场景1:校验RSA加密结果的正确性
如果只是要确认加密后的密文可以正常还原为原明文,不需要用Signature类,直接用私钥解密密文后和原明文对比即可:
import java.util.Arrays; // 省略原有密钥生成、明文定义、加密逻辑 // 新增解密校验逻辑 Cipher decryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); // 显式指定填充规则避免跨环境兼容问题 decryptCipher.init(Cipher.DECRYPT_MODE, kp.getPrivate()); byte[] decryptedText = decryptCipher.doFinal(encryptText); boolean result = Arrays.equals(plaintext, decryptedText); System.out.println(result); // 输出true
场景2:需要做数字签名验证
如果确实要实现签名校验能力,不要用Cipher加密的结果当签名,而是用私钥生成标准签名后再校验:
// 1. 私钥生成签名 Signature sig = Signature.getInstance("SHA256withRSA"); sig.initSign(kp.getPrivate()); sig.update(plaintext); byte[] signature = sig.sign(); // 此处输出的才是合法签名字节数组 // 2. 公钥验证签名 sig.initVerify(kp.getPublic()); sig.update(plaintext); boolean result = sig.verify(signature); System.out.println(result); // 输出true
内容的提问来源于stack exchange,提问作者An Dương
相关产品推荐
相关产品推荐

