Saturday, June 24, 2017

Java and SSL: How to Create a Self-signed Certificate Programmatically

This post is part of a series about the worlds of Java and SSL.  I hope to do 1 post a day on this topic. The resulting posts will become the basis for another section of a talk that I am scheduled to give on August 10 at the Boulder/Denver Cybersecurity Meetup.

How to Create a Self-signed Certificate Programmatically



public X509Certificate generateCertificate(String dn, KeyPair pair, int days, String algorithm)
         throws GeneralSecurityException, IOException {
    PrivateKey privkey = pair.getPrivate();
    X509CertInfo info = new X509CertInfo();
    Date from = new Date();
    Date to = new Date(from.getTime() + days * 86400000l);
    CertificateValidity interval = new CertificateValidity(from, to);
    BigInteger sn = new BigInteger(64, new SecureRandom());
    X500Name owner = new X500Name(dn);

    info.set(X509CertInfo.VALIDITY, interval);
    info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
    info.set(X509CertInfo.SUBJECT, owner);
    info.set(X509CertInfo.ISSUER, owner);
    info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic()));
    info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
    AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
    info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo));

    // Sign the cert to identify the algorithm that's used.
    X509CertImpl cert = new X509CertImpl(info);
    cert.sign(privkey, algorithm);

    // Update the algorith, and resign.
    algo = (AlgorithmId) cert.get(X509CertImpl.SIG_ALG);
    info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo);
    cert = new X509CertImpl(info);
    cert.sign(privkey, algorithm);
    return cert;
}

This was ridiculously difficult to figure out.  I kept getting an exception like this:

java.security.cert.CertificateException: Subject class type invalid.

But the problem was that the original code was using X509CertInfo.set instead of using an instance of X500Name.  

No comments:

Post a Comment