Android中使用SpongyCastle实现PKCS#7签名时算法异常求助
解决思路与方案
核心原因分析
- 依赖版本不匹配:你使用的SpongyCastle core(1.58.0.0)和pkix(1.54.0.0)版本不一致,可能导致算法注册表不兼容,引发找不到算法的问题。
- Provider与密钥绑定冲突:AndroidKeyStore生成的RSA密钥绑定在系统
AndroidKeyStoreProvider下,无法直接通过SpongyCastle的BCProvider初始化签名器——BC无法访问AndroidKeyStore受保护的密钥,且双方的算法命名、实现逻辑存在差异。
具体解决方案
1. 统一SpongyCastle依赖版本
将core和pkix依赖统一为同一版本,避免版本不兼容导致的算法映射异常:
implementation 'com.madgag.spongycastle:core:1.58.0.0' implementation 'com.madgag.spongycastle:pkix:1.58.0.0'
2. 用AndroidKeyStore Provider完成签名操作
由于密钥来自AndroidKeyStore,签名必须通过系统AndroidKeyStore Provider执行,再将签名结果整合到PKCS#7结构中。示例代码片段:
// 获取AndroidKeyStore中的私钥 KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); PrivateKey privateKey = (PrivateKey) keyStore.getKey("your_key_alias", null); X509Certificate cert = (X509Certificate) keyStore.getCertificate("your_key_alias"); // 初始化AndroidKeyStore签名实例 Signature signature = Signature.getInstance("SHA1withRSA", "AndroidKeyStore"); signature.initSign(privateKey); byte[] dataBytes = "your_string_to_sign".getBytes(StandardCharsets.UTF_8); signature.update(dataBytes); byte[] rawSignature = signature.sign(); // 用SpongyCastle构建PKCS#7签名数据 CMSSignedDataGenerator generator = new CMSSignedDataGenerator(); // 传入已生成的签名结果 ContentSigner signer = new ContentSigner() { @Override public AlgorithmIdentifier getAlgorithmIdentifier() { return new AlgorithmIdentifier(PKCSObjectIdentifiers.sha1WithRSAEncryption); } @Override public OutputStream getOutputStream() { return new ByteArrayOutputStream() { @Override public void close() throws IOException { super.close(); write(rawSignature); } }; } }; // 添加证书链与签名信息 generator.addSignerInfoGenerator( new JcaSignerInfoGeneratorBuilder( new JcaDigestCalculatorProviderBuilder().setProvider("SC").build() ).build(signer, cert) ); generator.addCertificate(new JcaX509CertificateHolder(cert)); // 生成最终PKCS#7数据 CMSTypedData cmsData = new CMSProcessableByteArray(dataBytes); CMSSignedData signedData = generator.generate(cmsData, false); byte[] pkcs7Bytes = signedData.getEncoded();
3. 规范算法名称写法
确保初始化签名时使用的算法名与Provider支持的一致,AndroidKeyStore与SpongyCastle均支持SHA1withRSA(大小写不敏感,但建议保持标准写法)。
4. 避免让SpongyCastle直接创建签名器
不要依赖CMSSignedDataGenerator通过BC Provider创建签名器,而是手动传入AndroidKeyStore生成的签名结果——既绕开了BC无法访问系统密钥的限制,又能利用SpongyCastle完成PKCS#7结构的构建。
内容的提问来源于stack exchange,提问作者Mohsen Einhesari
相关产品推荐
相关产品推荐

