I create a signed certificate with an existing CA as I explained in this post: Bouncy Castle: Signed Certificate with an existing CA
However, my generated certificate has the same public and private keys that the CA certificate.
Is it possible to generate a certificate which has another key pair?
I have tried the example code in the following post but my pdf signature is invalid: Generating X509 Certificate using Bouncy Castle Java
I will appreciate any comment or information that can help me.
Thanks in advance.
A public key certificate (PKC) will have the same key pair (public key) as the issuer only if the certificate is a self signed one. It's always possible for a CA to issue a certificate for another key-pair, in which case the new certificate will have the public key of the new key-pair and will be signed by the CA's private key. The subject of this new certificate can in turn be made a CA (through BasicConstraint extension and KeyUsage extension) in which case the new key-pair can be used to issue yet other certificates, thus creating a certificate path or chain. Please see the following code snippet.
public static X509Certificate getCertificte(X500Name subject,
PublicKey subjectPublicKey,
boolean isSubjectCA,
X509Certificate caCertificate,
PrivateKey caPrivateKey,
String signingAlgorithm,
Date validFrom,
Date validTill) throws CertificateEncodingException {
BigInteger sn = new BigInteger(64, random);
X500Name issuerName = new X500Name(caCertificate.getSubjectDN().getName());
SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(subjectPublicKey.getEncoded());
X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(issuerName,
sn,
validFrom,
validTill,
subject,
subjectPublicKeyInfo);
JcaX509ExtensionUtils extensionUtil;
try {
extensionUtil = new JcaX509ExtensionUtils();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("No provider found for SHA1 message-digest");
}
// Add extensions
try {
AuthorityKeyIdentifier authorityKeyIdentifier = extensionUtil.createAuthorityKeyIdentifier(caCertificate);
certBuilder.addExtension(Extension.authorityKeyIdentifier, false, authorityKeyIdentifier);
SubjectKeyIdentifier subjectKeyIdentifier = extensionUtil.createSubjectKeyIdentifier(subjectPublicKey);
certBuilder.addExtension(Extension.subjectKeyIdentifier, false, subjectKeyIdentifier);
BasicConstraints basicConstraints = new BasicConstraints(isSubjectCA);
certBuilder.addExtension(Extension.basicConstraints, true, basicConstraints);
} catch (CertIOException e) {
throw new RuntimeException("Could not add one or more extension(s)");
}
ContentSigner contentSigner;
try {
contentSigner = new JcaContentSignerBuilder(signingAlgorithm).build(caPrivateKey);
} catch (OperatorCreationException e) {
throw new RuntimeException("Could not generate certificate signer", e);
}
try {
return new JcaX509CertificateConverter().getCertificate(certBuilder.build(contentSigner));
} catch (CertificateException e) {
throw new RuntimeException("could not generate certificate", e);
}
}
Please note the arguments:
subjectPublicKey: public key corresponding to the new key-pair for which a new certificate will be issued.
caCertificate: CA certificate which corresponds to the key-pair of the current CA.
caPrivateKey: private key of the CA (private key corresponding to the caCertificate above). This will be used to sign the new certificate.
isSubjectCA: a boolean indicating whether the new certificate holder (subject) will be acting as a CA.
I have omitted keyUsage extensions for brevity, which should be used to indicate what all purposes the public key corresponding to the new cert should be used.