Android Java使用.cer公钥与.pfx私钥签名校验返回false问题排查
问题根源
- 哈希算法不匹配:你签名时使用的算法是
SHA256withRSA,但验签时用的是SHA512withRSA,二者哈希算法不一致,必然会导致校验失败。 - 空异常捕获隐藏错误:验签方法中的
catch块没有任何日志输出,即使出现证书加载失败、公钥不匹配、Base64解码错误等问题,也会直接返回false,无法定位具体问题。 - 证书配对风险:需要确认
xyx.cer是从abc.pfx对应的密钥对中导出的公钥证书,若两个证书不属于同一密钥对,校验也会失败。 - 私钥取错风险:你遍历KeyStore别名时,如果pfx文件内存在多个密钥条目,最终取到的是最后一个匹配条目的私钥,若该条目的公钥和
xyx.cer不对应也会失败。
修复方案
第一步:统一签名验签算法
将验签代码中的算法修改为和签名一致的SHA256withRSA,修改后的验签代码如下:
public static boolean validateSignature(Context context,String data, String signature) { try { InputStream is = context.getResources().openRawResource(R.raw.xyx); CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate crt = (X509Certificate) cf.generateCertificate(is); PublicKey publicKey = crt.getPublicKey(); byte[] bytes = data.getBytes(StandardCharsets.UTF_8); // 修正算法和签名端一致 Signature sig = Signature.getInstance("SHA256withRSA"); sig.initVerify(publicKey); sig.update(bytes); return sig.verify(Base64.decode(signature,Base64.NO_WRAP)); } catch (Exception ex) { // 增加日志输出,方便定位问题 ex.printStackTrace(); } return false; }
第二步:验证证书配对正确性
可以先从abc.pfx中导出公钥证书,和你当前的xyx.cer做比对,确认二者是同一密钥对的公私钥。
第三步:确认私钥读取正确性
如果pfx中存在多个密钥别名,可在遍历到符合条件的别名后直接break,避免被后续别名覆盖:
if (keyStore.isKeyEntry(alias)) { pkEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias, new KeyStore.PasswordProtection("1234".toCharArray())); pk = pkEntry.getPrivateKey(); // 匹配到目标密钥后直接退出循环 break; }
内容的提问来源于stack exchange,提问作者Tejas Telawane
相关产品推荐
相关产品推荐

