Davidm113021
Davidm113021

Reputation: 81

Generating an X509 Certificate in Java

I need to generate a public X509 Certificate but I have very little experience with Security in Java. I just want to make sure that what I am currently doing will work. First, I have already generated a public and private key with the following code:

public static void generateKeys() {
        try {
            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
            SecureRandom random = SecureRandom.getInstanceStrong();
            keyGen.initialize(2048, random);

            KeyPair pair = keyGen.generateKeyPair();
            PrivateKey priv = pair.getPrivate();
            PublicKey pub = pair.getPublic();
            byte[] encPriv = priv.getEncoded();
            FileOutputStream privfos = new FileOutputStream(PRIVATE_KEY_FILENAME);
            privfos.write(encPriv);
            privfos.close();

            byte[] encPub = pub.getEncoded();
            FileOutputStream pubfos = new FileOutputStream(PUBLIC_KEY_FILENAME);
            pubfos.write(encPub);
            pubfos.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

And here is the code used for generating the X509Certificate:

public static PrivateKey getPrivateKey() throws Exception {
    byte[] pkcs8EncodedBytes = Files.readAllBytes(PRIVATE_KEY_FILENAME);
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8EncodedBytes);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    return kf.generatePrivate(keySpec);
}

public static PublicKey getPublicKey() throws Exception {
    byte[] publicEncodedBytes = Files.readAllBytes(PUBLIC_KEY_FILENAME);
    X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicEncodedBytes);
    KeyFactory factory = KeyFactory.getInstance("RSA");
    return factory.generatePublic(publicKeySpec);
}

public static X509Certificate generateX509Certificate() throws Exception {
    PrivateKey privateKey = getPrivateKey();
    PublicKey publicKey = getPublicKey();
    KeyPair keyPair = new KeyPair(publicKey, privateKey);
    final Instant now = Instant.now();
    final Date notBefore = Date.from(now);
    final Date until = LocalDate.now().plusYears(100).toDate();
    final ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256WITHRSA").build(keyPair.getPrivate());
    final X500Name x500Name = new X500Name("CN=Common Name,O=Organization,L=City,ST=State");
    final X509v3CertificateBuilder certificateBuilder = new JcaX509v3CertificateBuilder(x500Name,
            BigInteger.valueOf(now.toEpochMilli()), notBefore, until, x500Name, keyPair.getPublic());
    return new JcaX509CertificateConverter().setProvider(new BouncyCastleProvider())
            .getCertificate(certificateBuilder.build(contentSigner));
}

Can someone clarify if this is the correct way to create a X509Certificate in Java? Thanks!

Upvotes: 3

Views: 9483

Answers (1)

Fiona Chen
Fiona Chen

Reputation: 1368

I haven't seen your loading a Key Store. Your method of retrieving the private/public key doesn't seem right.
A working example looks like this:

    public static Certificate generateCertificate(KeyPair keyPair) throws CertificateException, OperatorCreationException 
    {
        X500Name x500Name = new X500Name("CN=***.com, OU=Security&Defense, O=*** Crypto., L=Ottawa, ST=Ontario, C=CA");
        SubjectPublicKeyInfo pubKeyInfo = SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded());
        final Date start = new Date();
        final Date until = Date.from(LocalDate.now().plus(365, ChronoUnit.DAYS).atStartOfDay().toInstant(ZoneOffset.UTC));
        final X509v3CertificateBuilder certificateBuilder = new X509v3CertificateBuilder(x500Name,
                new BigInteger(10, new SecureRandom()), start,   until,  x500Name,  pubKeyInfo
        );
        ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256WithRSA").build(keyPair.getPrivate());

        Certificate certificate = new JcaX509CertificateConverter().setProvider(new BouncyCastleProvider()).getCertificate(certificateBuilder.build(contentSigner));
        
        System.out.println("x.509 certificate is successfully generated!");
        
        return certificate;
           
    }

Generate certificate logging:

Generating certificate in KeyStore /security/keystore/Andante-x509.jks

Encapsulating KeyPair with password in KeyStore... 

x.509 certificate is successfully generated!

Sitzung beendet wird. 

Extract and validate certificate from KeyStore:

If certificate doesn’t exist:

Certificate API Exception: The system cannot find the path specified. 

If KeyStore alias doesn’t match:

KeyStore Exception: Key cannot be retrieved. 

If KeyStore password doesn’t match:

KeyStore Exception: Keystore was tampered with, or password was incorrect. 

Upvotes: 3

Related Questions