/** * Copyright (C) 2015 Zero11 S.r.l. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package it.zero11.acme.utils; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.X500NameBuilder; import org.bouncycastle.asn1.x500.style.BCStyle; import org.bouncycastle.asn1.x509.AccessDescription; import org.bouncycastle.asn1.x509.AuthorityInformationAccess; import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.ExtensionsGenerator; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.GeneralNames; import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; import org.bouncycastle.openssl.jcajce.JcaPEMWriter; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.bouncycastle.pkcs.PKCS10CertificationRequest; import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder; import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder; public class X509Utils { public static final String DEFAULT_ALGHORITM = "RSA"; public static PKCS10CertificationRequest generateCSR(String[] commonNames, KeyPair pair) throws OperatorCreationException, IOException { X500NameBuilder namebuilder = new X500NameBuilder(X500Name.getDefaultStyle()); namebuilder.addRDN(BCStyle.CN, commonNames[0]); List<GeneralName> subjectAltNames = new ArrayList<>(commonNames.length); for (String cn:commonNames) subjectAltNames.add(new GeneralName(GeneralName.dNSName, cn)); GeneralNames subjectAltName = new GeneralNames(subjectAltNames.toArray(new GeneralName[0])); ExtensionsGenerator extGen = new ExtensionsGenerator(); extGen.addExtension(Extension.subjectAlternativeName, false, subjectAltName.toASN1Primitive()); PKCS10CertificationRequestBuilder p10Builder = new JcaPKCS10CertificationRequestBuilder(namebuilder.build(), pair.getPublic()); p10Builder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, extGen.generate()); JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder("SHA256withRSA"); ContentSigner signer = csBuilder.build(pair.getPrivate()); PKCS10CertificationRequest request = p10Builder.build(signer); return request; } public static KeyPair generateKeyPair(int size) throws NoSuchAlgorithmException { KeyPairGenerator keyGen = KeyPairGenerator.getInstance(DEFAULT_ALGHORITM); keyGen.initialize(size); return keyGen.generateKeyPair(); } public static KeyPair loadPEMKeyPair(InputStream privateKeyInputStream) throws IOException { try(PEMParser pemParser = new PEMParser(new InputStreamReader(privateKeyInputStream))){ PEMKeyPair keyPair = (PEMKeyPair) pemParser.readObject(); return new JcaPEMKeyConverter().getKeyPair(keyPair); } } public static void savePEM(OutputStream outputStream, Object object) throws IOException { try(JcaPEMWriter writer = new JcaPEMWriter(new PrintWriter(outputStream))){ writer.writeObject(object); } } public static String getCACertificateURL(X509Certificate certificate) throws IOException { byte[] bOctets = ((ASN1OctetString) ASN1Primitive.fromByteArray(certificate.getExtensionValue(Extension.authorityInfoAccess.getId()))).getOctets(); AuthorityInformationAccess access = AuthorityInformationAccess.getInstance(ASN1Sequence.fromByteArray(bOctets)); for (AccessDescription ad:access.getAccessDescriptions()){ if (ad.getAccessMethod().equals(X509ObjectIdentifiers.id_ad_caIssuers)){ return ad.getAccessLocation().getName().toString(); } } return null; } }