首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Bouncycastle编码PKCS7

用Bouncycastle编码PKCS7
EN

Stack Overflow用户
提问于 2019-07-17 00:17:07
回答 2查看 493关注 0票数 0

我的代码依赖于sun.security来生成一个用于签名APK的PKCS7签名块:

代码语言:javascript
复制
    private static void writeSignatureBlock(byte[] signatureBytes, X509Certificate publicKey, OutputStream out)
            throws Exception {
        SignerInfo signerInfo = new SignerInfo(new X500Name(publicKey.getIssuerX500Principal().getName()),
                publicKey.getSerialNumber(), AlgorithmId.get("SHA1"), AlgorithmId.get("RSA"), signatureBytes);

        PKCS7 pkcs7 = new PKCS7(new AlgorithmId[] { AlgorithmId.get("SHA1") },
                new ContentInfo(ContentInfo.DATA_OID, null), new X509Certificate[] { publicKey },
                new SignerInfo[] { signerInfo });

        ByteArrayOutputStream o = new ByteArrayOutputStream();
        pkcs7.encodeSignedData(o);
        byte[] expected = o.toByteArray();
    }

我正在尝试用Bouncy castle替换它,因为较新的Java版本不喜欢访问sun的内部类。

为了在bouncy castle中复制这种行为,我尝试了以下代码:

代码语言:javascript
复制
        List<java.security.cert.Certificate> certList = new ArrayList<java.security.cert.Certificate>();
        java.security.cert.Certificate certificate = publicKey;
        certList.add(certificate);
        JcaCertStore certs = new JcaCertStore(certList);
        CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
        gen.addCertificates(certs);

        final byte[] signedHash = signatureBytes;

        ContentSigner nonSigner = new ContentSigner() {

            @Override
            public byte[] getSignature() {
                return signedHash;
            }

            @Override
            public OutputStream getOutputStream() {
                return new ByteArrayOutputStream();
            }

            @Override
            public AlgorithmIdentifier getAlgorithmIdentifier() {
                return new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1WithRSA");
            }

        };

        org.bouncycastle.asn1.x509.Certificate cert = org.bouncycastle.asn1.x509.Certificate
                .getInstance(ASN1Primitive.fromByteArray(certificate.getEncoded()));
        JcaSignerInfoGeneratorBuilder sigb = new JcaSignerInfoGeneratorBuilder(
                new JcaDigestCalculatorProviderBuilder().build());
        sigb.setDirectSignature(true);
        gen.addSignerInfoGenerator(sigb.build(nonSigner, new X509CertificateHolder(cert)));
        CMSProcessableByteArray msg = new CMSProcessableByteArray(new byte[0]);

        CMSSignedData signedData = gen.generate(msg, false);
        byte[] bouncyCastle = signedData.getEncoded();

生成的输出具有不同的长度,并且非常不同:

代码语言:javascript
复制
Expected length: 1489
BouncyCastle length: 1491```

Why do these outputs differ in length (if only the content would be different I'd assume I supplied the data in a wrong format)?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-07-17 22:14:18

唯一的区别是Bouncycastle对证书主题中的某些字符串使用的编码与sun.*类略有不同。Bouncycastle更符合RFC3280,但RFC5280在一定程度上放宽了要求。任何一种编码都应该没问题。

票数 1
EN

Stack Overflow用户

发布于 2020-01-22 22:27:37

BouncyCastle的替代方案是来自Oracle的Osdt CERT库,可从Maven-Repository获得。Gradle依赖:

代码语言:javascript
复制
// https://mvnrepository.com/artifact/com.oracle.ojdbc/osdt_core
implementation "com.oracle.ojdbc:osdt_cert:19.3.0.0" 

Oracle库使用起来要简单得多,比Bouncy castle更简单。从现有的PKCS7格式生成X509 DER格式需要3行代码:

代码语言:javascript
复制
import oracle.security.crypto.cert.PKCS7;
import oracle.security.crypto.cert.X509;

        byte[] certDER = <retrieve the X.509 certificate as DER encoded byte array>
        X509 x509 = new X509(certAsDER);
        PKCS7 pkcs7 = new PKCS7(x509);
        byte pkcs7DER = pkcs7.getEncoded();
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57061591

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档