Java tutorial
/* * JBoss, Home of Professional Open Source. * Copyright 2012, Red Hat, Inc., and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.picketlink.pki.internal.util; import java.math.BigInteger; import java.security.KeyPair; import java.security.PrivateKey; import java.security.SecureRandom; import java.security.Security; import java.security.cert.X509Certificate; import java.util.Date; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.BasicConstraints; import org.bouncycastle.asn1.x509.ExtendedKeyUsage; import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.KeyPurposeId; import org.bouncycastle.asn1.x509.KeyUsage; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.X509ExtensionUtils; import org.bouncycastle.cert.X509v1CertificateBuilder; 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.DigestCalculator; import org.bouncycastle.operator.bc.BcDigestCalculatorProvider; import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.picketlink.pki.cert.CertificateAuthorityConfig; /** * The Class X509Util. * * @author Giriraj Sharma * @since December 2, 2014 */ public class X509Util { /** * Generates version 1 {@link java.security.cert.X509Certificate}. * * @param subjectDN the subject dn * @param caKeyPair the CA key pair * @param certificateConfig the certificate config * * @return the x509 certificate */ public static X509Certificate generateV1Certificate(X500Name subjectDN, KeyPair caKeyPair, CertificateAuthorityConfig certificateConfig) { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); try { BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis()); Date validityStartDate = new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000); Date validityEndDate = new Date( System.currentTimeMillis() + certificateConfig.getCertificateValidity() * 24 * 60 * 60 * 1000); SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo .getInstance(caKeyPair.getPublic().getEncoded()); X509v1CertificateBuilder builder = new X509v1CertificateBuilder(subjectDN, serialNumber, validityStartDate, validityEndDate, subjectDN, subPubKeyInfo); X509CertificateHolder holder = builder.build(createSigner(caKeyPair.getPrivate(), certificateConfig)); return new JcaX509CertificateConverter().getCertificate(holder); } catch (Exception e) { throw new RuntimeException("Error creating X509v1Certificate.", e); } } /** * Generate version 3 {@link java.security.cert.X509Certificate}. * * @param rootCertificate the root certificate * @param issuerKeyPair the issuer key pair * @param subjectDN the subject dn * @param subjectKeyPair the subject key pair * @param certificateConfig the certificate config * * @return the x509 certificate */ public static X509Certificate generateV3Certificate(X509Certificate rootCertificate, KeyPair issuerKeyPair, X500Name subjectDN, KeyPair subjectKeyPair, CertificateAuthorityConfig certificateConfig) { try { // Serial Number SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); BigInteger serialNumber = BigInteger.valueOf(Math.abs(random.nextInt())); // Validity Date notBefore = new Date(System.currentTimeMillis()); Date notAfter = new Date(System.currentTimeMillis() + (((1000L * 60 * 60 * 24 * 30)) * 12) * 3); // SubjectPublicKeyInfo SubjectPublicKeyInfo subjPubKeyInfo = new SubjectPublicKeyInfo( ASN1Sequence.getInstance(subjectKeyPair.getPublic().getEncoded())); X509v3CertificateBuilder certGen = new X509v3CertificateBuilder( new X500Name(rootCertificate.getSubjectDN().getName()), serialNumber, notBefore, notAfter, subjectDN, subjPubKeyInfo); DigestCalculator digCalc = new BcDigestCalculatorProvider() .get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1)); X509ExtensionUtils x509ExtensionUtils = new X509ExtensionUtils(digCalc); // Subject Key Identifier certGen.addExtension(Extension.subjectKeyIdentifier, false, x509ExtensionUtils.createSubjectKeyIdentifier(subjPubKeyInfo)); // Authority Key Identifier certGen.addExtension(Extension.authorityKeyIdentifier, false, x509ExtensionUtils.createAuthorityKeyIdentifier(subjPubKeyInfo)); // Key Usage certGen.addExtension(Extension.keyUsage, false, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyCertSign | KeyUsage.cRLSign)); // Extended Key Usage KeyPurposeId[] EKU = new KeyPurposeId[2]; EKU[0] = KeyPurposeId.id_kp_emailProtection; EKU[1] = KeyPurposeId.id_kp_serverAuth; certGen.addExtension(Extension.extendedKeyUsage, false, new ExtendedKeyUsage(EKU)); // Basic Constraints certGen.addExtension(Extension.basicConstraints, true, new BasicConstraints(0)); // Certificate Policies /* PolicyInformation[] certPolicies = new PolicyInformation[2]; certPolicies[0] = new PolicyInformation(new ASN1ObjectIdentifier("2.16.840.1.101.2.1.11.5")); certPolicies[1] = new PolicyInformation(new ASN1ObjectIdentifier("2.16.840.1.101.2.1.11.18")); certGen.addExtension(Extension.certificatePolicies, false, new CertificatePolicies(certPolicies)); // Authority Information Access AccessDescription caIssuers = new AccessDescription(AccessDescription.id_ad_caIssuers, new GeneralName( GeneralName.uniformResourceIdentifier, new DERIA5String("http://www.somewebsite.com/ca.cer"))); AccessDescription ocsp = new AccessDescription(AccessDescription.id_ad_ocsp, new GeneralName( GeneralName.uniformResourceIdentifier, new DERIA5String("http://ocsp.somewebsite.com"))); ASN1EncodableVector aia_ASN = new ASN1EncodableVector(); aia_ASN.add(caIssuers); aia_ASN.add(ocsp); certGen.addExtension(Extension.authorityInfoAccess, false, new DERSequence(aia_ASN)); // CRL Distribution Points DistributionPointName distPointOne = new DistributionPointName(new GeneralNames(new GeneralName( GeneralName.uniformResourceIdentifier, "http://crl.somewebsite.com/master.crl"))); DistributionPointName distPointTwo = new DistributionPointName( new GeneralNames( new GeneralName(GeneralName.uniformResourceIdentifier, "ldap://crl.somewebsite.com/cn%3dSecureCA%2cou%3dPKI%2co%3dCyberdyne%2cc%3dUS?certificaterevocationlist;binary"))); DistributionPoint[] distPoints = new DistributionPoint[2]; distPoints[0] = new DistributionPoint(distPointOne, null, null); distPoints[1] = new DistributionPoint(distPointTwo, null, null); certGen.addExtension(Extension.cRLDistributionPoints, false, new CRLDistPoint(distPoints));*/ // Content Signer ContentSigner sigGen = new JcaContentSignerBuilder("SHA1WithRSAEncryption").setProvider("BC") .build(issuerKeyPair.getPrivate()); // Certificate return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certGen.build(sigGen)); } catch (Exception e) { throw new RuntimeException("Error creating X509v3Certificate.", e); } } /** * Creates the content signer for generation of Version 1 {@link java.security.cert.X509Certificate}. * * @param privateKey the private key * @param certificateConfig the certificate config * * @return the content signer */ public static ContentSigner createSigner(PrivateKey privateKey, CertificateAuthorityConfig certificateConfig) { try { AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder() .find(certificateConfig.getSignatureAlgorithm()); 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); } } }