Android验证RSA-SHA512签名遇ASN.1编码错误求助
RSA-SHA512签名验证的ASN.1编码错误排查与解决
问题背景
我尝试使用public.cer验证.pass文件的签名,签名算法为带PKCS1填充的RSA-SHA512,目标SDK版本32。编写的验证方法在解析证书时抛出ASN.1编码错误,同时想确认PKCS1填充是否需要额外配置。
验证方法代码
public boolean validateSignature(Context context, byte[] data, byte[] signature) { try { // Reading public certificate from raw folder InputStream is = context.getResources().openRawResource(R.raw.public_cer); CertificateFactory cf = CertificateFactory.getInstance("X.509"); // This line is giving error X509Certificate crt = (X509Certificate) cf.generateCertificate(is); PublicKey publicKey = crt.getPublicKey(); Signature sig = Signature.getInstance("SHA512withRSA"); sig.initVerify(publicKey); sig.update(data); return sig.verify(Base64.decode(signature, Base64.NO_WRAP)); } catch (Exception ex) { Log.d(TAG, ex.getLocalizedMessage()); } return false; }
调用代码
if (validateSignature( applicationContext, bytes, // Byte array of Data file signatureBytes // Byte array of signature file ) ) { Log.d(TAG, "checkSignature: true"); } else { Log.d(TAG, "checkSignature: false"); }
错误信息
com.android.org.conscrypt.OpenSSLX509CertificateFactory$ParsingException: java.lang.RuntimeException: error:0c0000be:ASN.1 encoding routines:OPENSSL_internal:WRONG_TAG
问题解答
关于PKCS1填充的配置
不需要额外配置。SHA512withRSA在Java/Android环境中默认采用PKCS#1 v1.5填充,完全匹配你的算法要求,这部分代码逻辑是正确的。
ASN.1编码错误的原因与修复
错误WRONG_TAG的核心是系统无法正确解析public.cer文件,以下是具体排查和修复步骤:
1. 检查证书文件格式与完整性
- 确认证书是标准X.509格式:
- PEM格式证书需包含首尾标记:
-----BEGIN CERTIFICATE-----和-----END CERTIFICATE-----,中间为Base64编码内容 - DER格式是二进制文件,不可用文本编辑器修改,避免引入多余字符
- PEM格式证书需包含首尾标记:
- 用OpenSSL工具验证证书有效性:
若命令能输出证书详细信息则证书有效;若报错,说明证书损坏或格式错误,需重新获取正确的公钥证书。openssl x509 -in public.cer -text -noout
2. 适配PEM格式证书的读取逻辑
如果你的public.cer是PEM格式,直接用CertificateFactory读取会失败,需先去除首尾标记再解码:
public boolean validateSignature(Context context, byte[] data, byte[] signature) { try { InputStream is = context.getResources().openRawResource(R.raw.public_cer); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder pemContent = new StringBuilder(); String line; boolean inCertBlock = false; while ((line = reader.readLine()) != null) { if (line.startsWith("-----BEGIN CERTIFICATE-----")) { inCertBlock = true; continue; } if (line.startsWith("-----END CERTIFICATE-----")) { inCertBlock = false; break; } if (inCertBlock) { pemContent.append(line.trim()); } } byte[] certBytes = Base64.decode(pemContent.toString(), Base64.DEFAULT); CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate crt = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(certBytes)); PublicKey publicKey = crt.getPublicKey(); Signature sig = Signature.getInstance("SHA512withRSA"); sig.initVerify(publicKey); sig.update(data); return sig.verify(Base64.decode(signature, Base64.NO_WRAP)); } catch (Exception ex) { Log.d(TAG, ex.getLocalizedMessage()); ex.printStackTrace(); } return false; }
3. 确认签名数据的正确性
确保signatureBytes是签名的原始二进制数据,或正确解码后的字节数组:
- 若签名文件是Base64文本格式,需先读取文本内容再调用
Base64.decode,而非直接读取二进制文件。
内容的提问来源于stack exchange,提问作者Niral Bhavsar
相关产品推荐
相关产品推荐

