Closed jpstotz closed 2 years ago
Your code is actually creating the AlgorithmIdentifier with null instead of DERNull.INSTANCE. That goes into the SubjectPublicKeyInfo and is preserved into the generated certificate.
If you would let BC generate the SubjectPublicKeyInfo it would be created correctly AFAICT. e.g:
SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(pubKey.getEncoded());
@peterdettman Thanks for pointing that out. It is pretty hard to use that classes as there is nearly no documentation (JavaDoc) and the classes itself do not seem to validate their arguments.
Using new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE);
works.
SubjectPublicKeyInfo.getInstance(pubKey.getEncoded());
also works and allows to delete a lot of other code as well.
Just for the records (in case somebody else needs to do the same) the updated code is:
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(keysize);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey pubKey = (RSAPublicKey) keyPair.getPublic();
ContentSigner sigGen = new JcaContentSignerBuilder(SIGNATURE_ALGO).build(caPrivateKey);
SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(pubKey.getEncoded());
Calendar startDate = Calendar.getInstance();
Calendar endDate = Calendar.getInstance();
endDate.add(Calendar.YEAR, 5);
X500Name subjectX500 = new X500Name(RFC4519Style.INSTANCE, subject);
X500Name issuerX500 = new X500Name(RFC4519Style.INSTANCE, caCert.getSubjectDN().getName());
X509v3CertificateBuilder v3CertGen = new X509v3CertificateBuilder(issuerX500, BigInteger.valueOf(serial),
startDate.getTime(), endDate.getTime(), subjectX500, subPubKeyInfo);
v3CertGen.addExtension(Extension.basicConstraints, false, new BasicConstraints(false));
v3CertGen.addExtension(Extension.keyUsage, false, new KeyUsage( KeyUsage.digitalSignature | KeyUsage.nonRepudiation | KeyUsage.keyEncipherment));
v3CertGen.addExtension(Extension.subjectAlternativeName, false, new GeneralNames("example.org"));
X509CertificateHolder certHolder = v3CertGen.build(sigGen);
byte[] certData = certHolder.getEncoded();
I am using BouncyCastle 1.70 to generate and sign a server certificate with an RSA key. The problem is that the ASN.1 structure of the generated X509 certificate contains an invalid RSA public key.
The main problem is e.g. discussed here: https://github.com/zmap/zlint/issues/283:
The sequence containing the OID is generated by BouncyCastle this way:
But correct would be:
Most implementations don't care for the missing
NULL
value but some do. And according to the linked discussion the specification is clear that theNULL
value has to be included.Sample code used for generating RSA key and certificate: