org.vesalainen.security.cert.X509Generator.java Source code

Java tutorial

Introduction

Here is the source code for org.vesalainen.security.cert.X509Generator.java

Source

/*
 * Copyright (C) 2016 Timo Vesalainen <timo.vesalainen@iki.fi>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.vesalainen.security.cert;

import java.math.BigInteger;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Date;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.style.RFC4519Style;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;
import org.vesalainen.lang.Primitives;

/**
 *
 * @author Timo Vesalainen <timo.vesalainen@iki.fi>
 */
public class X509Generator {

    /**
     * Create a self-signed X.509 Certificate
     *
     * @param subjectDN the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB"
     * @param pair the KeyPair
     * @param days how many days from now the Certificate is valid for
     * @param algorithm the signing algorithm, e.g. "SHA1withRSA"
     * @return 
     * @throws java.security.cert.CertificateException 
     */
    public X509Certificate generateSelfSignedCertificate(String subjectDN, KeyPair pair, int days, String algorithm)
            throws CertificateException {
        return generateCertificate(subjectDN, null, pair, null, days, algorithm);
    }

    /**
     * Create a signed X.509 Certificate
     * @param subjectDN the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB"
     * @param issuerDN Signers X.509 Distinguished Name, eg "CN=Test, L=London, C=GB"
     * @param pair the KeyPair
     * @param privkey Signers private key
     * @param days how many days from now the Certificate is valid for
     * @param signingAlgorithm the signing algorithm, e.g. "SHA1withRSA"
     * @return 
     * @throws java.security.cert.CertificateException 
     */
    public X509Certificate generateCertificate(String subjectDN, String issuerDN, KeyPair pair, PrivateKey privkey,
            int days, String signingAlgorithm) throws CertificateException {
        if (privkey == null) {
            privkey = pair.getPrivate();
        }
        X500Name issuer;
        if (issuerDN == null) {
            issuer = new X500Name(RFC4519Style.INSTANCE, subjectDN);
        } else {
            issuer = new X500Name(RFC4519Style.INSTANCE, issuerDN);
        }
        long now = System.currentTimeMillis();
        BigInteger serial = BigInteger.probablePrime(64, new SecureRandom(Primitives.writeLong(now)));
        X500Name subject = new X500Name(RFC4519Style.INSTANCE, subjectDN);
        PublicKey publicKey = pair.getPublic();
        byte[] encoded = publicKey.getEncoded();
        SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(encoded);
        X509v3CertificateBuilder builder = new X509v3CertificateBuilder(issuer, serial, new Date(now - 86400000l),
                new Date(now + days * 86400000l), subject, subjectPublicKeyInfo);
        X509CertificateHolder holder = builder.build(createSigner(privkey, signingAlgorithm));
        return new JcaX509CertificateConverter().getCertificate(holder);
    }

    public static ContentSigner createSigner(PrivateKey privateKey, String signingAlgorithm) {
        try {
            AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find(signingAlgorithm);
            AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);

            return new BcRSAContentSignerBuilder(sigAlgId, digAlgId)
                    .build(PrivateKeyFactory.createKey(privateKey.getEncoded()));
        } catch (Exception e) {
            throw new RuntimeException("Could not create content signer.", e);
        }
    }
}