Java tutorial
/* * Copyright (c) LinkedIn Corporation. All rights reserved. Licensed under the BSD-2 Clause license. * See LICENSE in the project root for license information. */ package com.linkedin.mitm.services; import com.linkedin.mitm.model.CertificateAuthority; import com.linkedin.mitm.model.CertificateValidPeriod; import java.io.ByteArrayInputStream; import java.io.IOException; import java.math.BigInteger; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Security; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Date; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.X500NameBuilder; import org.bouncycastle.asn1.x500.style.BCStyle; import org.bouncycastle.asn1.x509.SubjectKeyIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.cert.X509v3CertificateBuilder; import org.bouncycastle.cert.bc.BcX509ExtensionUtils; import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; /** * Abstract X509 certificate service that implement functionality that * commonly used for other X509 certificate service * * @author shfeng */ public abstract class AbstractX509CertificateService { static { Security.addProvider(new BouncyCastleProvider()); } private static final String SIGNATURE_ALGORITHM = "SHA1WithRSAEncryption"; private final CertificateAuthority _certificateAuthority; private final CertificateValidPeriod _certificateValidPeriod; protected AbstractX509CertificateService(CertificateAuthority certificateAuthority, CertificateValidPeriod certificateValidPeriod) { _certificateAuthority = certificateAuthority; _certificateValidPeriod = certificateValidPeriod; } protected BigInteger getSerial() { return BigInteger.valueOf(RandomNumberGenerator.getInstance().getSecureRandom().nextLong()); } /** * Create subjectKeyIdentifier * The Subject Key Identifier extension identifies the public key certified by this certificate. * This extension provides a way of distinguishing public keys if more than one is available for * a given subject name. * i.e. * Identifier: Subject Key Identifier - 2.5.29.14 * Critical: no * Key Identifier: * 3B:46:83:85:27:BC:F5:9D:8E:63:E3:BE:79:EF:AF:79: * 9C:37:85:84 * * */ protected SubjectKeyIdentifier createSubjectKeyIdentifier(PublicKey publicKey) throws IOException { try (ByteArrayInputStream bais = new ByteArrayInputStream(publicKey.getEncoded()); ASN1InputStream ais = new ASN1InputStream(bais)) { ASN1Sequence asn1Sequence = (ASN1Sequence) ais.readObject(); SubjectPublicKeyInfo subjectPublicKeyInfo = new SubjectPublicKeyInfo(asn1Sequence); return new BcX509ExtensionUtils().createSubjectKeyIdentifier(subjectPublicKeyInfo); } } protected X509Certificate createCertificate(PrivateKey privateKey, X509v3CertificateBuilder x509v3CertificateBuilder) throws OperatorCreationException, CertificateException { ContentSigner contentSigner = new JcaContentSignerBuilder(SIGNATURE_ALGORITHM) .setProvider(BouncyCastleProvider.PROVIDER_NAME).build(privateKey); X509Certificate x509Certificate = new JcaX509CertificateConverter() .setProvider(BouncyCastleProvider.PROVIDER_NAME) .getCertificate(x509v3CertificateBuilder.build(contentSigner)); return x509Certificate; } protected X500Name getSubject(String commonName) { X500NameBuilder x500NameBuilder = new X500NameBuilder(BCStyle.INSTANCE); x500NameBuilder.addRDN(BCStyle.CN, commonName); x500NameBuilder.addRDN(BCStyle.O, _certificateAuthority.getOrganization()); x500NameBuilder.addRDN(BCStyle.OU, _certificateAuthority.getOrganizationalUnit()); return x500NameBuilder.build(); } protected Date getValidDateFrom() { return _certificateValidPeriod.getStart(); } protected Date getValidDateTo() { return _certificateValidPeriod.getEnd(); } protected void updateKeyStore(KeyStore keystore, PrivateKey privateKey, Certificate[] certificates) throws KeyStoreException { keystore.setKeyEntry(_certificateAuthority.getAlias(), privateKey, _certificateAuthority.getPassPhrase(), certificates); } /** * Build X.509 v3 Certificate extension * @param x509v3CertificateBuilder certificate builder * @param publicKey certificate public key * */ protected abstract void buildExtensions(X509v3CertificateBuilder x509v3CertificateBuilder, PublicKey publicKey) throws IOException; }