Bouncy Castle:使用现有 CA 签名的证书
Bouncy Castle: Signed Certificate with an existing CA
我正在尝试创建一个证书 (A),该证书已为存储在 p12 密钥库中的其他证书 (B) 签名。此存储的证书 (B) 已添加到我本地计算机的受信任证书存储区。
证书A用于使用bouncy castle 1.52库对pdf文档进行签名,但我在签名文档中获取的数字签名无效。
如果有人能帮助我,我将解释完成的步骤。
首先,我从 p12 密钥库 (B) 创建一个 CSR:
private static PKCS10CertificationRequest generateCSR() {
PKCS10CertificationRequest csr = null;
try {
initCACert();
PKCS10CertificationRequestBuilder p10Builder = new JcaPKCS10CertificationRequestBuilder(
new X500Principal("CN=Requested Test Certificate"), CAcert.getPublicKey());
JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder("SHA256withRSA");
ContentSigner signer = csBuilder.build(CApk);
csr = p10Builder.build(signer);
} catch (Exception e) {
log.error(e);
}
return csr;
}
然后,使用此 CSR 生成证书 (A)。
private static Certificate signCSR() throws Exception {
PKCS10CertificationRequest csr = generateCSR();
AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256withRSA");
AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
X500Name issuer = X500Name.getInstance(CAcert.getSubjectX500Principal().getEncoded());
BigInteger serial = new BigInteger(32, new SecureRandom());
Calendar c = Calendar.getInstance();
c.add(Calendar.SECOND, -1);
Date from = c.getTime();
c.add(Calendar.YEAR, 5);
Date to = c.getTime();
X509v1CertificateBuilder certBuilder = new X509v1CertificateBuilder(issuer, serial, from, to, csr.getSubject(),
csr.getSubjectPublicKeyInfo());
ContentSigner signer = new BcRSAContentSignerBuilder(sigAlgId, digAlgId)
.build(PrivateKeyFactory.createKey(CApk.getEncoded()));
X509CertificateHolder holder = certBuilder.build(signer);
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
InputStream in = new ByteArrayInputStream(holder.getEncoded());
Certificate cert = certFactory.generateCertificate(in);
return cert;
}
最后,我使用这个生成的证书 (A) 来签署我的 pdf。
Certificate cert = signCSR();
SignerInfoGeneratorBuilder signerInfoBuilder = new SignerInfoGeneratorBuilder(
new JcaDigestCalculatorProviderBuilder().setProvider("BC").build()
);
signerInfoBuilder.setSignedAttributeGenerator( signedAttributeGenerator );
JcaContentSignerBuilder contentSignerBuilder = new JcaContentSignerBuilder( "SHA1WITHRSA" );
contentSignerBuilder.setProvider("BC");
X509CertificateHolder certificateHolder = new X509CertificateHolder( cert.getEncoded( ) );
generator.addSignerInfoGenerator(
signerInfoBuilder.build( contentSignerBuilder.build( CApk ),
certificateHolder )
);
ArrayList<X509CertificateHolder> signingChainHolder = new ArrayList<X509CertificateHolder>( );
certificateHolder = new X509CertificateHolder( cert.getEncoded() );
certificateHolder = new X509CertificateHolder( CAcert.getEncoded() );
signingChainHolder.add( certificateHolder );
Store certs = new JcaCertStore( signingChainHolder );
generator.addCertificates( certs );
CMSTypedData content = new CMSProcessableByteArray(datos);
CMSSignedData signedData = generator.generate( content, true );
ByteArrayOutputStream baos = new ByteArrayOutputStream();
new DEROutputStream(baos).writeObject(signedData.toASN1Structure());
result = baos.toByteArray();
所有的过程显然都执行正确,但是当我打开pdf时签名无效:
编辑:我导出了生成的证书。这是得到的结果。
如果有任何评论或信息可以帮助我解决此问题,我将不胜感激。
提前致谢。
generator.addSignerInfoGenerator(
signerInfoBuilder.build( contentSignerBuilder.build( CApk ),
certificateHolder )
);
如果我没看错,您正在使用 CA 的私钥对数据进行签名。应该是证书的。因此私钥和 public 密钥不匹配,因此签名验证检查失败。
我发现了问题:我以相反的顺序构建证书链。
我有这个订单:
certificateHolder = new X509CertificateHolder( cert.getEncoded() );
certificateHolder = new X509CertificateHolder( CAcert.getEncoded() );
正确的顺序是:
certificateHolder = new X509CertificateHolder( CAcert.getEncoded() );
certificateHolder = new X509CertificateHolder( cert.getEncoded() );
我希望有人能找到有用的信息!
我正在尝试创建一个证书 (A),该证书已为存储在 p12 密钥库中的其他证书 (B) 签名。此存储的证书 (B) 已添加到我本地计算机的受信任证书存储区。
证书A用于使用bouncy castle 1.52库对pdf文档进行签名,但我在签名文档中获取的数字签名无效。
如果有人能帮助我,我将解释完成的步骤。
首先,我从 p12 密钥库 (B) 创建一个 CSR:
private static PKCS10CertificationRequest generateCSR() {
PKCS10CertificationRequest csr = null;
try {
initCACert();
PKCS10CertificationRequestBuilder p10Builder = new JcaPKCS10CertificationRequestBuilder(
new X500Principal("CN=Requested Test Certificate"), CAcert.getPublicKey());
JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder("SHA256withRSA");
ContentSigner signer = csBuilder.build(CApk);
csr = p10Builder.build(signer);
} catch (Exception e) {
log.error(e);
}
return csr;
}
然后,使用此 CSR 生成证书 (A)。
private static Certificate signCSR() throws Exception {
PKCS10CertificationRequest csr = generateCSR();
AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256withRSA");
AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
X500Name issuer = X500Name.getInstance(CAcert.getSubjectX500Principal().getEncoded());
BigInteger serial = new BigInteger(32, new SecureRandom());
Calendar c = Calendar.getInstance();
c.add(Calendar.SECOND, -1);
Date from = c.getTime();
c.add(Calendar.YEAR, 5);
Date to = c.getTime();
X509v1CertificateBuilder certBuilder = new X509v1CertificateBuilder(issuer, serial, from, to, csr.getSubject(),
csr.getSubjectPublicKeyInfo());
ContentSigner signer = new BcRSAContentSignerBuilder(sigAlgId, digAlgId)
.build(PrivateKeyFactory.createKey(CApk.getEncoded()));
X509CertificateHolder holder = certBuilder.build(signer);
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
InputStream in = new ByteArrayInputStream(holder.getEncoded());
Certificate cert = certFactory.generateCertificate(in);
return cert;
}
最后,我使用这个生成的证书 (A) 来签署我的 pdf。
Certificate cert = signCSR();
SignerInfoGeneratorBuilder signerInfoBuilder = new SignerInfoGeneratorBuilder(
new JcaDigestCalculatorProviderBuilder().setProvider("BC").build()
);
signerInfoBuilder.setSignedAttributeGenerator( signedAttributeGenerator );
JcaContentSignerBuilder contentSignerBuilder = new JcaContentSignerBuilder( "SHA1WITHRSA" );
contentSignerBuilder.setProvider("BC");
X509CertificateHolder certificateHolder = new X509CertificateHolder( cert.getEncoded( ) );
generator.addSignerInfoGenerator(
signerInfoBuilder.build( contentSignerBuilder.build( CApk ),
certificateHolder )
);
ArrayList<X509CertificateHolder> signingChainHolder = new ArrayList<X509CertificateHolder>( );
certificateHolder = new X509CertificateHolder( cert.getEncoded() );
certificateHolder = new X509CertificateHolder( CAcert.getEncoded() );
signingChainHolder.add( certificateHolder );
Store certs = new JcaCertStore( signingChainHolder );
generator.addCertificates( certs );
CMSTypedData content = new CMSProcessableByteArray(datos);
CMSSignedData signedData = generator.generate( content, true );
ByteArrayOutputStream baos = new ByteArrayOutputStream();
new DEROutputStream(baos).writeObject(signedData.toASN1Structure());
result = baos.toByteArray();
所有的过程显然都执行正确,但是当我打开pdf时签名无效:
编辑:我导出了生成的证书。这是得到的结果。
如果有任何评论或信息可以帮助我解决此问题,我将不胜感激。
提前致谢。
generator.addSignerInfoGenerator(
signerInfoBuilder.build( contentSignerBuilder.build( CApk ),
certificateHolder )
);
如果我没看错,您正在使用 CA 的私钥对数据进行签名。应该是证书的。因此私钥和 public 密钥不匹配,因此签名验证检查失败。
我发现了问题:我以相反的顺序构建证书链。
我有这个订单:
certificateHolder = new X509CertificateHolder( cert.getEncoded() );
certificateHolder = new X509CertificateHolder( CAcert.getEncoded() );
正确的顺序是:
certificateHolder = new X509CertificateHolder( CAcert.getEncoded() );
certificateHolder = new X509CertificateHolder( cert.getEncoded() );
我希望有人能找到有用的信息!