问题
I'm trying to create a certificate (A) which is signed for other certificate (B) stored in a p12 keystore. This stored certificate (B) was added to the trusted certificate store of my local machine.
Certificate A is used to sign a pdf document using bouncy castle 1.52 library, but the digital signature that I obtain in the signed document is invalid.
I'm going to explain the steps done just if somebody can help me.
First, I create a CSR from the p12 keystore(B):
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;
}
Then, a certificate was generated (A) with this CSR.
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;
}
Finally, I use this generated certificate (A) to sign my 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();
All the process is executed apparently right, but when I open the pdf the signature is invalid:
EDIT: I have made an export of the generated certificate. This is the result obtained.
I will appreciate any comment or information that can help me to fix this.
Thanks in advance.
回答1:
generator.addSignerInfoGenerator(
signerInfoBuilder.build( contentSignerBuilder.build( CApk ),
certificateHolder )
);
If I see that right, you're using the CA's private key to sign the data. It should be the certificate's. So private and public key don't match and therefor a signature validation check is failing.
回答2:
I have identified the problem: I was building the certificate chain in the opposite order that should be.
I had this order:
certificateHolder = new X509CertificateHolder( cert.getEncoded() );
certificateHolder = new X509CertificateHolder( CAcert.getEncoded() );
And the right order is this:
certificateHolder = new X509CertificateHolder( CAcert.getEncoded() );
certificateHolder = new X509CertificateHolder( cert.getEncoded() );
I hope somebody can find this information useful!
来源:https://stackoverflow.com/questions/51750354/bouncy-castle-signed-certificate-with-an-existing-ca