You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中使用SpongyCastle实现PKCS#7签名时算法异常求助

解决思路与方案

核心原因分析

  1. 依赖版本不匹配:你使用的SpongyCastle core(1.58.0.0)和pkix(1.54.0.0)版本不一致,可能导致算法注册表不兼容,引发找不到算法的问题。
  2. Provider与密钥绑定冲突:AndroidKeyStore生成的RSA密钥绑定在系统AndroidKeyStore Provider下,无法直接通过SpongyCastle的BC Provider初始化签名器——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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 12:25:14