How can I add something like a number to a X509 v3 Certificate?
X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(
new X500Name("CN=Subject"),
serialNumber,
startDate, expiryDate,
new X500Name("CN=CA"),
interPubInfo);
Think this works with .addExtension()
but what comes after?
As told in the comments, you can't just add arbitrary values anywhere in the certificate.
If you want to do it just for test or study purposes, you could use the Subject Alternative Name extension. This extension has some optional fields with a more "free" format:
OtherName ::= SEQUENCE {
type-id OBJECT IDENTIFIER,
value [0] EXPLICIT ANY DEFINED BY type-id }
So you could add an OtherName
field with the values you want. The problem is the type-id
field, because Object Identifiers can't be arbitrary values - they're actually standardized.
In a real-life scenario, you can't use the code below, because I'm using some arbitrary identifier (1.2.3.4.5.6.7.8.9) just to make it work. For a production certificate, you should use only pre-defined existent values.
That being said, I've made this code (in BouncyCastle 1.56) to add the extension with the value 123:
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.GeneralNames;
int number = 123;
ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier("1.2.3.4.5.6.7.8.9"); // some arbitrary non-existent OID number
DERSequence seq = new DERSequence(new ASN1Encodable[] { oid, new ASN1Integer(number) });
ArrayList<GeneralName> namesList = new ArrayList<>();
namesList.add(new GeneralName(GeneralName.otherName, seq));
GeneralNames subjectAltNames = GeneralNames.getInstance(new DERSequence((GeneralName[]) namesList.toArray(new GeneralName[] {})));
// certBuilder is a X509v3CertificateBuilder
certBuilder.addExtension(Extension.subjectAlternativeName, false, subjectAltNames);
To read this extension from the certificate:
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.x509.extension.X509ExtensionUtil;
X509Certificate cert = // a java.security.cert.X509Certificate
byte[] v = cert.getExtensionValue(Extension.subjectAlternativeName.getId());
GeneralNames gn = GeneralNames.getInstance(X509ExtensionUtil.fromExtensionValue(v));
GeneralName[] names = gn.getNames();
for (GeneralName name : names) {
if (name.getTagNo() == GeneralName.otherName) {
ASN1Sequence seq = ASN1Sequence.getInstance(name.getName());
if ("1.2.3.4.5.6.7.8.9".equals(oid.getId())) { // OID is the arbitrary one I created
ASN1Integer value = (ASN1Integer) seq.getObjectAt(1);
int number = value.getValue().intValue();
System.out.println(number); // number is 123
}
}
}