Java tutorial
/* * * This file is part of the XiPKI project. * Copyright (c) 2014 - 2015 Lijun Liao * Author: Lijun Liao * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License version 3 * as published by the Free Software Foundation with the addition of the * following permission added to Section 15 as permitted in Section 7(a): * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY * THE AUTHOR LIJUN LIAO. LIJUN LIAO DISCLAIMS THE WARRANTY OF NON INFRINGEMENT * OF THIRD PARTY RIGHTS. * * 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU Affero General Public License. * * You can be released from the requirements of the license by purchasing * a commercial license. Buying such a license is mandatory as soon as you * develop commercial activities involving the XiPKI software without * disclosing the source code of your own applications. * * For more information, please contact Lijun Liao at this * address: lijun.liao@gmail.com */ package org.xipki.ca.certprofile.internal; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.URL; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.validation.SchemaFactory; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.sec.SECObjectIdentifiers; import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.w3c.dom.Element; import org.xipki.ca.api.profile.x509.SpecialX509CertprofileBehavior; import org.xipki.ca.certprofile.XmlX509Certprofile; import org.xipki.ca.certprofile.x509.jaxb.Admission; import org.xipki.ca.certprofile.x509.jaxb.AlgorithmType; import org.xipki.ca.certprofile.x509.jaxb.AnyType; import org.xipki.ca.certprofile.x509.jaxb.AuthorityInfoAccess; import org.xipki.ca.certprofile.x509.jaxb.AuthorityKeyIdentifier; import org.xipki.ca.certprofile.x509.jaxb.BasicConstraints; import org.xipki.ca.certprofile.x509.jaxb.CertificatePolicies; import org.xipki.ca.certprofile.x509.jaxb.CertificatePolicyInformationType; import org.xipki.ca.certprofile.x509.jaxb.ConstantExtValue; import org.xipki.ca.certprofile.x509.jaxb.DSAParameters; import org.xipki.ca.certprofile.x509.jaxb.ECParameters; import org.xipki.ca.certprofile.x509.jaxb.ECParameters.Curves; import org.xipki.ca.certprofile.x509.jaxb.ECParameters.PointEncodings; import org.xipki.ca.certprofile.x509.jaxb.ExtendedKeyUsage; import org.xipki.ca.certprofile.x509.jaxb.ExtendedKeyUsage.Usage; import org.xipki.ca.certprofile.x509.jaxb.ExtensionType; import org.xipki.ca.certprofile.x509.jaxb.ExtensionValueType; import org.xipki.ca.certprofile.x509.jaxb.ExtensionsType; import org.xipki.ca.certprofile.x509.jaxb.GeneralNameType; import org.xipki.ca.certprofile.x509.jaxb.GeneralNameType.OtherName; import org.xipki.ca.certprofile.x509.jaxb.GeneralSubtreeBaseType; import org.xipki.ca.certprofile.x509.jaxb.GeneralSubtreesType; import org.xipki.ca.certprofile.x509.jaxb.InhibitAnyPolicy; import org.xipki.ca.certprofile.x509.jaxb.KeyParametersType; import org.xipki.ca.certprofile.x509.jaxb.KeyUsage; import org.xipki.ca.certprofile.x509.jaxb.KeyUsageEnum; import org.xipki.ca.certprofile.x509.jaxb.NameConstraints; import org.xipki.ca.certprofile.x509.jaxb.NameValueType; import org.xipki.ca.certprofile.x509.jaxb.ObjectFactory; import org.xipki.ca.certprofile.x509.jaxb.OidWithDescType; import org.xipki.ca.certprofile.x509.jaxb.PolicyConstraints; import org.xipki.ca.certprofile.x509.jaxb.PolicyIdMappingType; import org.xipki.ca.certprofile.x509.jaxb.PolicyMappings; import org.xipki.ca.certprofile.x509.jaxb.RSAParameters; import org.xipki.ca.certprofile.x509.jaxb.RangeType; import org.xipki.ca.certprofile.x509.jaxb.RangesType; import org.xipki.ca.certprofile.x509.jaxb.RdnType; import org.xipki.ca.certprofile.x509.jaxb.SubjectAltName; import org.xipki.ca.certprofile.x509.jaxb.SubjectInfoAccess; import org.xipki.ca.certprofile.x509.jaxb.UsageType; import org.xipki.ca.certprofile.x509.jaxb.X509ProfileType; import org.xipki.ca.certprofile.x509.jaxb.X509ProfileType.KeyAlgorithms; import org.xipki.ca.certprofile.x509.jaxb.X509ProfileType.Parameters; import org.xipki.ca.certprofile.x509.jaxb.X509ProfileType.SignatureAlgorithms; import org.xipki.ca.certprofile.x509.jaxb.X509ProfileType.Subject; import org.xipki.common.ObjectIdentifiers; import org.xipki.common.util.SecurityUtil; import org.xipki.common.util.StringUtil; import org.xipki.common.util.XMLUtil; import org.xml.sax.SAXException; /** * @author Lijun Liao */ public class ProfileConfCreatorDemo { private static final ASN1ObjectIdentifier id_gematik = new ASN1ObjectIdentifier("1.2.276.0.76.4"); private static final String REGEX_FQDN = "(?=^.{1,254}$)(^(?:(?!\\d+\\.|-)[a-zA-Z0-9_\\-]{1,63}(?<!-)\\.?)+(?:[a-zA-Z]{2,})$)"; private static final String REGEX_SN = "[\\d]{1,}"; private static final Set<ASN1ObjectIdentifier> requestExtensions; static { requestExtensions = new HashSet<>(); requestExtensions.add(Extension.keyUsage); requestExtensions.add(Extension.extendedKeyUsage); requestExtensions.add(Extension.subjectAlternativeName); requestExtensions.add(Extension.subjectInfoAccess); } private static class ExampleDescription extends AnyType { public ExampleDescription(final Element appInfo) { setAny(appInfo); } } public static void main(final String[] args) { try { Marshaller m = JAXBContext.newInstance(ObjectFactory.class).createMarshaller(); final SchemaFactory schemaFact = SchemaFactory .newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI); URL url = XmlX509Certprofile.class.getResource("/xsd/certprofile.xsd"); m.setSchema(schemaFact.newSchema(url)); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); m.setProperty("com.sun.xml.internal.bind.indentString", " "); // RootCA X509ProfileType profile = Certprofile_RootCA(); marshall(m, profile, "Certprofile_RootCA.xml"); // Cross profile = Certprofile_Cross(); marshall(m, profile, "Certprofile_Cross.xml"); // SubCA profile = Certprofile_SubCA(); marshall(m, profile, "Certprofile_SubCA.xml"); profile = Certprofile_SubCA_Complex(); marshall(m, profile, "Certprofile_SubCA_Complex.xml"); // OCSP profile = Certprofile_OCSP(); marshall(m, profile, "Certprofile_OCSP.xml"); // TLS profile = Certprofile_TLS(); marshall(m, profile, "Certprofile_TLS.xml"); // TLS_C profile = Certprofile_TLS_C(); marshall(m, profile, "Certprofile_TLS_C.xml"); // TLSwithIncSN profile = Certprofile_TLSwithIncSN(); marshall(m, profile, "Certprofile_TLSwithIncSN.xml"); //gSMC-K profile = Certprofile_gSMC_K(); marshall(m, profile, "Certprofile_gSMC_K.xml"); //multiple-OUs profile = Certprofile_MultipleOUs(); marshall(m, profile, "Certprofile_multipleOUs.xml"); } catch (Exception e) { e.printStackTrace(); } } private static void marshall(final Marshaller m, final X509ProfileType profile, final String filename) throws Exception { File file = new File("tmp", filename); file.getParentFile().mkdirs(); JAXBElement<X509ProfileType> root = new ObjectFactory().createX509Profile(profile); FileOutputStream out = new FileOutputStream(file); try { m.marshal(root, out); } catch (JAXBException e) { throw XMLUtil.convert(e); } finally { out.close(); } } private static X509ProfileType Certprofile_RootCA() throws Exception { X509ProfileType profile = getBaseProfile("Certprofile RootCA", true, "10y", false, new String[] { "SHA256", "SHA1" }); // Subject Subject subject = profile.getSubject(); subject.setIncSerialNumber(false); List<RdnType> rdnControls = subject.getRdn(); rdnControls.add(createRDN(ObjectIdentifiers.DN_C, 1, 1, new String[] { "DE|FR" }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_O, 1, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_OU, 0, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_SN, 0, 1, new String[] { REGEX_SN }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_CN, 1, 1)); // Extensions ExtensionsType extensions = profile.getExtensions(); List<ExtensionType> list = extensions.getExtension(); list.add(createExtension(Extension.subjectKeyIdentifier, true, false, null)); list.add(createExtension(Extension.cRLDistributionPoints, false, false, null)); list.add(createExtension(Extension.freshestCRL, false, false, null)); // Extensions - basicConstraints ExtensionValueType extensionValue = null; list.add(createExtension(Extension.basicConstraints, true, true, extensionValue)); // Extensions - AuthorityInfoAccess extensionValue = createAuthorityInfoAccess(); list.add(createExtension(Extension.authorityInfoAccess, true, false, extensionValue)); // Extensions - keyUsage extensionValue = createKeyUsages(new KeyUsageEnum[] { KeyUsageEnum.KEY_CERT_SIGN }, new KeyUsageEnum[] { KeyUsageEnum.C_RL_SIGN }); list.add(createExtension(Extension.keyUsage, true, true, extensionValue)); return profile; } private static X509ProfileType Certprofile_Cross() throws Exception { X509ProfileType profile = getBaseProfile("Certprofile Cross", true, "10y", false, new String[] { "SHA256", "SHA1" }); // Subject Subject subject = profile.getSubject(); subject.setIncSerialNumber(false); List<RdnType> rdnControls = subject.getRdn(); rdnControls.add(createRDN(ObjectIdentifiers.DN_C, 1, 1, new String[] { "DE|FR" }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_O, 1, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_OU, 0, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_SN, 0, 1, new String[] { REGEX_SN }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_CN, 1, 1)); // Extensions ExtensionsType extensions = profile.getExtensions(); List<ExtensionType> list = extensions.getExtension(); list.add(createExtension(Extension.subjectKeyIdentifier, true, false, null)); list.add(createExtension(Extension.cRLDistributionPoints, false, false, null)); list.add(createExtension(Extension.freshestCRL, false, false, null)); // Extensions - basicConstraints ExtensionValueType extensionValue = null; list.add(createExtension(Extension.basicConstraints, true, true, extensionValue)); // Extensions - AuthorityInfoAccess extensionValue = createAuthorityInfoAccess(); list.add(createExtension(Extension.authorityInfoAccess, true, false, extensionValue)); // Extensions - AuthorityKeyIdentifier extensionValue = createAuthorityKeyIdentifier(false); list.add(createExtension(Extension.authorityKeyIdentifier, true, false, extensionValue)); // Extensions - keyUsage extensionValue = createKeyUsages(new KeyUsageEnum[] { KeyUsageEnum.KEY_CERT_SIGN }, null); list.add(createExtension(Extension.keyUsage, true, true, extensionValue)); return profile; } private static X509ProfileType Certprofile_SubCA() throws Exception { X509ProfileType profile = getBaseProfile("Certprofile SubCA", true, "8y", false, new String[] { "SHA256", "SHA1" }); // Subject Subject subject = profile.getSubject(); subject.setIncSerialNumber(false); List<RdnType> rdnControls = subject.getRdn(); rdnControls.add(createRDN(ObjectIdentifiers.DN_C, 1, 1, new String[] { "DE|FR" }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_O, 1, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_OU, 0, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_SN, 0, 1, new String[] { REGEX_SN }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_CN, 1, 1)); // Extensions ExtensionsType extensions = profile.getExtensions(); // Extensions - controls List<ExtensionType> list = extensions.getExtension(); list.add(createExtension(Extension.subjectKeyIdentifier, true, false, null)); list.add(createExtension(Extension.cRLDistributionPoints, false, false, null)); list.add(createExtension(Extension.freshestCRL, false, false, null)); // Extensions - basicConstraints ExtensionValueType extensionValue = createBasicConstraints(1); list.add(createExtension(Extension.basicConstraints, true, true, extensionValue)); // Extensions - AuthorityInfoAccess extensionValue = createAuthorityInfoAccess(); list.add(createExtension(Extension.authorityInfoAccess, true, false, extensionValue)); // Extensions - AuthorityKeyIdentifier extensionValue = createAuthorityKeyIdentifier(false); list.add(createExtension(Extension.authorityKeyIdentifier, true, false, extensionValue)); // Extensions - keyUsage extensionValue = createKeyUsages(new KeyUsageEnum[] { KeyUsageEnum.KEY_CERT_SIGN }, new KeyUsageEnum[] { KeyUsageEnum.C_RL_SIGN }); list.add(createExtension(Extension.keyUsage, true, true, extensionValue)); return profile; } private static X509ProfileType Certprofile_SubCA_Complex() throws Exception { X509ProfileType profile = getBaseProfile("Certprofile SubCA with most extensions", true, "8y", false, new String[] { "SHA256", "SHA1" }); // Subject Subject subject = profile.getSubject(); subject.setIncSerialNumber(false); List<RdnType> rdnControls = subject.getRdn(); rdnControls.add(createRDN(ObjectIdentifiers.DN_C, 1, 1, new String[] { "DE|FR" }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_O, 1, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_OU, 0, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_SN, 0, 1, new String[] { REGEX_SN }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_CN, 1, 1, null, "PREFIX ", " SUFFIX")); // Extensions ExtensionsType extensions = profile.getExtensions(); List<ExtensionType> list = extensions.getExtension(); list.add(createExtension(Extension.subjectKeyIdentifier, true, false, null)); list.add(createExtension(Extension.cRLDistributionPoints, false, false, null)); list.add(createExtension(Extension.freshestCRL, false, false, null)); // Extensions - basicConstraints ExtensionValueType extensionValue = createBasicConstraints(1); list.add(createExtension(Extension.basicConstraints, true, true, extensionValue)); // Extensions - AuthorityInfoAccess extensionValue = createAuthorityInfoAccess(); list.add(createExtension(Extension.authorityInfoAccess, true, false, extensionValue)); // Extensions - AuthorityKeyIdentifier extensionValue = createAuthorityKeyIdentifier(false); list.add(createExtension(Extension.authorityKeyIdentifier, true, false, extensionValue)); // Extensions - keyUsage extensionValue = createKeyUsages(new KeyUsageEnum[] { KeyUsageEnum.KEY_CERT_SIGN }, new KeyUsageEnum[] { KeyUsageEnum.C_RL_SIGN }); list.add(createExtension(Extension.keyUsage, true, true, extensionValue)); // Certificate Policies extensionValue = createCertificatePolicies(new ASN1ObjectIdentifier("1.2.3.4.5"), new ASN1ObjectIdentifier("2.4.3.2.1")); list.add(createExtension(Extension.certificatePolicies, true, false, extensionValue)); // Policy Mappings PolicyMappings policyMappings = new PolicyMappings(); policyMappings.getMapping().add(createPolicyIdMapping(new ASN1ObjectIdentifier("1.1.1.1.1"), new ASN1ObjectIdentifier("2.1.1.1.1"))); policyMappings.getMapping().add(createPolicyIdMapping(new ASN1ObjectIdentifier("1.1.1.1.2"), new ASN1ObjectIdentifier("2.1.1.1.2"))); extensionValue = createExtensionValueType(policyMappings); list.add(createExtension(Extension.policyMappings, true, true, extensionValue)); // Policy Constraints PolicyConstraints policyConstraints = createPolicyConstraints(2, 2); extensionValue = createExtensionValueType(policyConstraints); list.add(createExtension(Extension.policyConstraints, true, true, extensionValue)); // Name Constrains NameConstraints nameConstraints = createNameConstraints(); extensionValue = createExtensionValueType(nameConstraints); list.add(createExtension(Extension.nameConstraints, true, true, extensionValue)); // Inhibit anyPolicy InhibitAnyPolicy inhibitAnyPolicy = createInhibitAnyPolicy(1); extensionValue = createExtensionValueType(inhibitAnyPolicy); list.add(createExtension(Extension.inhibitAnyPolicy, true, true, extensionValue)); // SubjectAltName SubjectAltName subjectAltNameMode = new SubjectAltName(); OtherName otherName = new OtherName(); otherName.getType().add(createOidType(ObjectIdentifiers.DN_O)); subjectAltNameMode.setOtherName(otherName); subjectAltNameMode.setRfc822Name(""); subjectAltNameMode.setDNSName(""); subjectAltNameMode.setDirectoryName(""); subjectAltNameMode.setEdiPartyName(""); subjectAltNameMode.setUniformResourceIdentifier(""); subjectAltNameMode.setIPAddress(""); subjectAltNameMode.setRegisteredID(""); extensionValue = createExtensionValueType(subjectAltNameMode); list.add(createExtension(Extension.subjectAlternativeName, true, false, extensionValue)); // SubjectInfoAccess SubjectInfoAccess subjectInfoAccessMode = new SubjectInfoAccess(); SubjectInfoAccess.Access access = new SubjectInfoAccess.Access(); access.setAccessMethod(createOidType(ObjectIdentifiers.id_ad_caRepository)); GeneralNameType accessLocation = new GeneralNameType(); access.setAccessLocation(accessLocation); accessLocation.setDirectoryName(""); accessLocation.setUniformResourceIdentifier(""); subjectInfoAccessMode.getAccess().add(access); extensionValue = createExtensionValueType(subjectInfoAccessMode); list.add(createExtension(Extension.subjectInfoAccess, true, false, extensionValue)); // Custom Extension ASN1ObjectIdentifier customExtensionOid = new ASN1ObjectIdentifier("1.2.3.4"); extensionValue = createConstantExtValue(DERNull.INSTANCE.getEncoded()); list.add(createExtension(customExtensionOid, true, false, extensionValue, "custom extension 1")); return profile; } private static X509ProfileType Certprofile_OCSP() throws Exception { X509ProfileType profile = getBaseProfile("Certprofile OCSP", false, "5y", false, new String[] { "SHA256" }); // Subject Subject subject = profile.getSubject(); subject.setIncSerialNumber(false); List<RdnType> rdnControls = subject.getRdn(); rdnControls.add(createRDN(ObjectIdentifiers.DN_C, 1, 1, new String[] { "DE|FR" }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_O, 1, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_OU, 0, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_SN, 0, 1, new String[] { REGEX_SN }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_CN, 1, 1)); // Extensions ExtensionsType extensions = profile.getExtensions(); List<ExtensionType> list = extensions.getExtension(); list.add(createExtension(Extension.subjectKeyIdentifier, true, false, null)); list.add(createExtension(Extension.cRLDistributionPoints, false, false, null)); list.add(createExtension(Extension.freshestCRL, false, false, null)); list.add(createExtension(ObjectIdentifiers.id_extension_pkix_ocsp_nocheck, false, false, null)); // Extensions - basicConstraints ExtensionValueType extensionValue = null; list.add(createExtension(Extension.basicConstraints, true, true, extensionValue)); // Extensions - AuthorityInfoAccess extensionValue = createAuthorityInfoAccess(); list.add(createExtension(Extension.authorityInfoAccess, true, false, extensionValue)); // Extensions - AuthorityKeyIdentifier extensionValue = createAuthorityKeyIdentifier(true); list.add(createExtension(Extension.authorityKeyIdentifier, true, false, extensionValue)); // Extensions - keyUsage extensionValue = createKeyUsages(new KeyUsageEnum[] { KeyUsageEnum.CONTENT_COMMITMENT }, null); list.add(createExtension(Extension.keyUsage, true, true, extensionValue)); // Extensions - extenedKeyUsage extensionValue = createExtendedKeyUsage(new ASN1ObjectIdentifier[] { ObjectIdentifiers.id_kp_OCSPSigning }, null); list.add(createExtension(Extension.extendedKeyUsage, true, false, extensionValue)); return profile; } private static X509ProfileType Certprofile_TLS() throws Exception { X509ProfileType profile = getBaseProfile("Certprofile TLS", false, "5y", true, new String[] { "SHA1" }); // Subject Subject subject = profile.getSubject(); subject.setIncSerialNumber(false); List<RdnType> rdnControls = subject.getRdn(); rdnControls.add(createRDN(ObjectIdentifiers.DN_C, 1, 1, new String[] { "DE|FR" }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_O, 1, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_OU, 0, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_SN, 0, 1, new String[] { REGEX_SN }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_CN, 1, 1, new String[] { REGEX_FQDN }, null, null)); // Extensions // Extensions - general ExtensionsType extensions = profile.getExtensions(); // Extensions - controls List<ExtensionType> list = extensions.getExtension(); list.add(createExtension(Extension.subjectKeyIdentifier, true, false, null)); list.add(createExtension(Extension.cRLDistributionPoints, false, false, null)); list.add(createExtension(Extension.freshestCRL, false, false, null)); // Extensions - basicConstraints ExtensionValueType extensionValue = null; list.add(createExtension(Extension.basicConstraints, true, true, extensionValue)); // Extensions - AuthorityInfoAccess extensionValue = createAuthorityInfoAccess(); list.add(createExtension(Extension.authorityInfoAccess, true, false, extensionValue)); // Extensions - AuthorityKeyIdentifier extensionValue = createAuthorityKeyIdentifier(true); list.add(createExtension(Extension.authorityKeyIdentifier, true, false, extensionValue)); // Extensions - keyUsage extensionValue = createKeyUsages(new KeyUsageEnum[] { KeyUsageEnum.DIGITAL_SIGNATURE, KeyUsageEnum.DATA_ENCIPHERMENT, KeyUsageEnum.KEY_ENCIPHERMENT }, null); list.add(createExtension(Extension.keyUsage, true, true, extensionValue)); // Extensions - extenedKeyUsage extensionValue = createExtendedKeyUsage(new ASN1ObjectIdentifier[] { ObjectIdentifiers.id_kp_serverAuth }, new ASN1ObjectIdentifier[] { ObjectIdentifiers.id_kp_clientAuth }); list.add(createExtension(Extension.extendedKeyUsage, true, false, extensionValue)); // Admission - just DEMO, does not belong to TLS certificate extensionValue = createAdmission(new ASN1ObjectIdentifier("1.1.1.2"), "demo item"); list.add(createExtension(ObjectIdentifiers.id_extension_admission, true, false, extensionValue)); return profile; } private static X509ProfileType Certprofile_TLS_C() throws Exception { X509ProfileType profile = getBaseProfile("Certprofile TLS_C", false, "5y", false, new String[] { "SHA1" }); // Subject Subject subject = profile.getSubject(); subject.setIncSerialNumber(false); List<RdnType> rdnControls = subject.getRdn(); rdnControls.add(createRDN(ObjectIdentifiers.DN_C, 1, 1, new String[] { "DE|FR" }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_O, 1, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_OU, 0, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_SN, 0, 1, new String[] { REGEX_SN }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_CN, 1, 1)); // Extensions ExtensionsType extensions = profile.getExtensions(); List<ExtensionType> list = extensions.getExtension(); list.add(createExtension(Extension.subjectKeyIdentifier, true, false, null)); list.add(createExtension(Extension.cRLDistributionPoints, false, false, null)); list.add(createExtension(Extension.freshestCRL, false, false, null)); // Extensions - basicConstraints ExtensionValueType extensionValue = null; list.add(createExtension(Extension.basicConstraints, true, true, extensionValue)); // Extensions - AuthorityInfoAccess extensionValue = createAuthorityInfoAccess(); list.add(createExtension(Extension.authorityInfoAccess, true, false, extensionValue)); // Extensions - AuthorityKeyIdentifier extensionValue = createAuthorityKeyIdentifier(true); list.add(createExtension(Extension.authorityKeyIdentifier, true, false, extensionValue)); // Extensions - keyUsage extensionValue = createKeyUsages(new KeyUsageEnum[] { KeyUsageEnum.DIGITAL_SIGNATURE, KeyUsageEnum.DATA_ENCIPHERMENT, KeyUsageEnum.KEY_ENCIPHERMENT }, null); list.add(createExtension(Extension.keyUsage, true, true, extensionValue)); // Extensions - extenedKeyUsage extensionValue = createExtendedKeyUsage(new ASN1ObjectIdentifier[] { ObjectIdentifiers.id_kp_clientAuth }, null); list.add(createExtension(Extension.extendedKeyUsage, true, false, extensionValue)); return profile; } private static X509ProfileType Certprofile_TLSwithIncSN() throws Exception { X509ProfileType profile = getBaseProfile("Certprofile TLSwithIncSN", false, "5y", false, new String[] { "SHA1" }); // Subject Subject subject = profile.getSubject(); subject.setIncSerialNumber(true); List<RdnType> rdnControls = subject.getRdn(); rdnControls.add(createRDN(ObjectIdentifiers.DN_C, 1, 1, new String[] { "DE|FR" }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_O, 1, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_OU, 0, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_SN, 0, 1, new String[] { REGEX_SN }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_CN, 1, 1, new String[] { REGEX_FQDN }, null, null)); // Extensions // Extensions - general ExtensionsType extensions = profile.getExtensions(); // Extensions - controls List<ExtensionType> list = extensions.getExtension(); list.add(createExtension(Extension.subjectKeyIdentifier, true, false, null)); list.add(createExtension(Extension.cRLDistributionPoints, false, false, null)); list.add(createExtension(Extension.freshestCRL, false, false, null)); // Extensions - basicConstraints ExtensionValueType extensionValue = null; list.add(createExtension(Extension.basicConstraints, true, true, extensionValue)); // Extensions - AuthorityInfoAccess extensionValue = createAuthorityInfoAccess(); list.add(createExtension(Extension.authorityInfoAccess, true, false, extensionValue)); // Extensions - AuthorityKeyIdentifier extensionValue = createAuthorityKeyIdentifier(true); list.add(createExtension(Extension.authorityKeyIdentifier, true, false, extensionValue)); // Extensions - keyUsage extensionValue = createKeyUsages(new KeyUsageEnum[] { KeyUsageEnum.DIGITAL_SIGNATURE, KeyUsageEnum.DATA_ENCIPHERMENT, KeyUsageEnum.KEY_ENCIPHERMENT }, null); list.add(createExtension(Extension.keyUsage, true, true, extensionValue)); // Extensions - extenedKeyUsage extensionValue = createExtendedKeyUsage(new ASN1ObjectIdentifier[] { ObjectIdentifiers.id_kp_serverAuth }, new ASN1ObjectIdentifier[] { ObjectIdentifiers.id_kp_clientAuth }); list.add(createExtension(Extension.extendedKeyUsage, true, false, extensionValue)); return profile; } private static X509ProfileType Certprofile_gSMC_K() throws Exception { X509ProfileType profile = getBaseProfile("Certprofile gSMC_K", false, "5y", false, new String[] { "SHA256" }); profile.setDuplicateSubject(true); // SpecialBehavior profile.setSpecialBehavior(SpecialX509CertprofileBehavior.gematik_gSMC_K.name()); // Maximal liftime Parameters profileParams = new Parameters(); profile.setParameters(profileParams); NameValueType nv = new NameValueType(); nv.setName(SpecialX509CertprofileBehavior.PARAMETER_MAXLIFTIME); nv.setValue(Integer.toString(20 * 365)); profileParams.getParameter().add(nv); // Subject Subject subject = profile.getSubject(); subject.setIncSerialNumber(false); List<RdnType> rdnControls = subject.getRdn(); rdnControls.add(createRDN(ObjectIdentifiers.DN_C, 1, 1, new String[] { "DE" }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_O, 1, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_OU, 0, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_ST, 0, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_L, 0, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_POSTAL_CODE, 0, 1)); rdnControls.add(createRDN(ObjectIdentifiers.DN_STREET, 0, 1)); // regex: ICCSN-yyyyMMdd String regex = "80276[\\d]{15,15}-20\\d\\d(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])"; rdnControls.add(createRDN(ObjectIdentifiers.DN_CN, 1, 1, new String[] { regex }, null, null)); // Extensions ExtensionsType extensions = profile.getExtensions(); List<ExtensionType> list = extensions.getExtension(); list.add(createExtension(Extension.subjectKeyIdentifier, true, false, null)); list.add(createExtension(Extension.cRLDistributionPoints, false, false, null)); // Extensions - basicConstraints ExtensionValueType extensionValue = null; list.add(createExtension(Extension.basicConstraints, true, true, extensionValue)); // Extensions - AuthorityInfoAccess extensionValue = createAuthorityInfoAccess(); list.add(createExtension(Extension.authorityInfoAccess, true, false, extensionValue)); // Extensions - AuthorityKeyIdentifier extensionValue = createAuthorityKeyIdentifier(true); list.add(createExtension(Extension.authorityKeyIdentifier, true, false, extensionValue)); // Extensions - keyUsage extensionValue = createKeyUsages( new KeyUsageEnum[] { KeyUsageEnum.DIGITAL_SIGNATURE, KeyUsageEnum.KEY_ENCIPHERMENT }, null); list.add(createExtension(Extension.keyUsage, true, true, extensionValue)); // Extensions - extenedKeyUsage extensionValue = createExtendedKeyUsage(new ASN1ObjectIdentifier[] { ObjectIdentifiers.id_kp_serverAuth }, new ASN1ObjectIdentifier[] { ObjectIdentifiers.id_kp_clientAuth }); list.add(createExtension(Extension.extendedKeyUsage, true, false, extensionValue)); // Extensions - Policy CertificatePolicies policies = new CertificatePolicies(); ASN1ObjectIdentifier[] policyIds = new ASN1ObjectIdentifier[] { id_gematik.branch("79"), id_gematik.branch("163") }; for (ASN1ObjectIdentifier id : policyIds) { CertificatePolicyInformationType policyInfo = new CertificatePolicyInformationType(); policies.getCertificatePolicyInformation().add(policyInfo); policyInfo.setPolicyIdentifier(createOidType(id)); } extensionValue = createExtensionValueType(policies); list.add(createExtension(Extension.certificatePolicies, true, false, extensionValue)); // Extension - Adminssion Admission admission = new Admission(); admission.getProfessionOid().add(createOidType(id_gematik.branch("103"))); admission.getProfessionItem().add("Anwendungskonnektor"); extensionValue = createExtensionValueType(admission); list.add(createExtension(ObjectIdentifiers.id_extension_admission, true, false, extensionValue)); // SubjectAltNames extensionValue = null; list.add(createExtension(Extension.subjectAlternativeName, false, false, extensionValue)); return profile; } private static X509ProfileType Certprofile_MultipleOUs() throws Exception { X509ProfileType profile = getBaseProfile("Certprofile Multiple OUs DEMO", false, "5y", false, new String[] { "SHA1" }); // Subject Subject subject = profile.getSubject(); subject.setIncSerialNumber(false); List<RdnType> rdnControls = subject.getRdn(); rdnControls.add(createRDN(ObjectIdentifiers.DN_C, 1, 1, new String[] { "DE|FR" }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_O, 1, 1)); final String regex_ou1 = "[A-Z]{1,1}[\\d]{5,5}"; final String regex_ou2 = "[\\d]{5,5}"; rdnControls .add(createRDN(ObjectIdentifiers.DN_OU, 2, 2, new String[] { regex_ou1, regex_ou2 }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_SN, 0, 1, new String[] { REGEX_SN }, null, null)); rdnControls.add(createRDN(ObjectIdentifiers.DN_CN, 1, 1)); // Extensions // Extensions - general ExtensionsType extensions = profile.getExtensions(); List<ExtensionType> list = extensions.getExtension(); list.add(createExtension(Extension.subjectKeyIdentifier, true, false, null)); list.add(createExtension(Extension.cRLDistributionPoints, false, false, null)); list.add(createExtension(Extension.freshestCRL, false, false, null)); // Extensions - basicConstraints ExtensionValueType extensionValue = null; list.add(createExtension(Extension.basicConstraints, true, true, extensionValue)); // Extensions - AuthorityInfoAccess extensionValue = createAuthorityInfoAccess(); list.add(createExtension(Extension.authorityInfoAccess, true, false, extensionValue)); // Extensions - AuthorityKeyIdentifier extensionValue = createAuthorityKeyIdentifier(true); list.add(createExtension(Extension.authorityKeyIdentifier, true, false, extensionValue)); // Extensions - keyUsage extensionValue = createKeyUsages(new KeyUsageEnum[] { KeyUsageEnum.CONTENT_COMMITMENT }, null); list.add(createExtension(Extension.keyUsage, true, true, extensionValue)); return profile; } private static RdnType createRDN(final ASN1ObjectIdentifier type, final int min, final int max) { return createRDN(type, min, max, null, null, null); } private static RdnType createRDN(final ASN1ObjectIdentifier type, final int min, final int max, final String[] regexArrays, final String prefix, final String suffix) { RdnType ret = new RdnType(); ret.setType(createOidType(type)); ret.setMinOccurs(min); ret.setMaxOccurs(max); if (regexArrays != null) { if (regexArrays.length != max) { throw new IllegalArgumentException("regexArrays.length " + regexArrays.length + " != max " + max); } for (String regex : regexArrays) { ret.getRegex().add(regex); } } if (StringUtil.isNotBlank(prefix)) { ret.setPrefix(prefix); } if (StringUtil.isNotBlank(suffix)) { ret.setSuffix(suffix); } return ret; } private static ExtensionType createExtension(final ASN1ObjectIdentifier type, final boolean required, final boolean critical, final ExtensionValueType extValue) { return createExtension(type, required, critical, extValue, null); } private static ExtensionType createExtension(final ASN1ObjectIdentifier type, final boolean required, final boolean critical, final ExtensionValueType extValue, final String description) { ExtensionType ret = new ExtensionType(); // abbributes ret.setRequired(required); ret.setPermittedInRequest(requestExtensions.contains(type)); // children ret.setType(createOidType(type, description)); ret.setCritical(critical); ret.setValue(extValue); return ret; } private static ExtensionValueType createKeyUsages(final KeyUsageEnum[] requiredUsages, final KeyUsageEnum[] optionalUsages) { KeyUsage extValue = new KeyUsage(); if (requiredUsages != null) { for (KeyUsageEnum m : requiredUsages) { UsageType usage = new UsageType(); usage.setValue(m); usage.setRequired(true); extValue.getUsage().add(usage); } } if (optionalUsages != null) { for (KeyUsageEnum m : optionalUsages) { UsageType usage = new UsageType(); usage.setValue(m); usage.setRequired(false); extValue.getUsage().add(usage); } } return createExtensionValueType(extValue); } private static ExtensionValueType createAuthorityKeyIdentifier(final boolean includeSerialAndSerial) { AuthorityKeyIdentifier akiType = new AuthorityKeyIdentifier(); akiType.setIncludeIssuerAndSerial(includeSerialAndSerial); return createExtensionValueType(akiType); } private static ExtensionValueType createAuthorityInfoAccess() { AuthorityInfoAccess extnValue = new AuthorityInfoAccess(); extnValue.setIncludeCaIssuers(true); extnValue.setIncludeOcsp(true); return createExtensionValueType(extnValue); } private static ExtensionValueType createBasicConstraints(final int pathLen) { BasicConstraints extValue = new BasicConstraints(); extValue.setPathLen(pathLen); return createExtensionValueType(extValue); } private static ExtensionValueType createExtendedKeyUsage(final ASN1ObjectIdentifier[] requiredUsages, final ASN1ObjectIdentifier[] optionalUsages) { ExtendedKeyUsage extValue = new ExtendedKeyUsage(); if (requiredUsages != null) { for (ASN1ObjectIdentifier usage : requiredUsages) { extValue.getUsage().add(createSingleExtKeyUsage(usage, true)); } } if (optionalUsages != null) { for (ASN1ObjectIdentifier usage : optionalUsages) { extValue.getUsage().add(createSingleExtKeyUsage(usage, false)); } } return createExtensionValueType(extValue); } private static Usage createSingleExtKeyUsage(final ASN1ObjectIdentifier usage, final boolean required) { Usage type = new Usage(); type.setValue(usage.getId()); type.setRequired(required); String desc = getDescription(usage); if (desc != null) { type.setDescription(desc); } return type; } private static ExtensionValueType createAdmission(final ASN1ObjectIdentifier oid, final String item) { Admission extValue = new Admission(); extValue.getProfessionItem().add(item); extValue.getProfessionOid().add(createOidType(oid)); return createExtensionValueType(extValue); } private static ExtensionValueType createCertificatePolicies(final ASN1ObjectIdentifier... policyOids) { if (policyOids == null || policyOids.length == 0) { return null; } CertificatePolicies extValue = new CertificatePolicies(); List<CertificatePolicyInformationType> l = extValue.getCertificatePolicyInformation(); for (ASN1ObjectIdentifier oid : policyOids) { CertificatePolicyInformationType single = new CertificatePolicyInformationType(); l.add(single); single.setPolicyIdentifier(createOidType(oid)); } return createExtensionValueType(extValue); } private static String getDescription(final ASN1ObjectIdentifier oid) { return ObjectIdentifiers.getName(oid); } private static PolicyIdMappingType createPolicyIdMapping(final ASN1ObjectIdentifier issuerPolicyId, final ASN1ObjectIdentifier subjectPolicyId) { PolicyIdMappingType ret = new PolicyIdMappingType(); ret.setIssuerDomainPolicy(createOidType(issuerPolicyId)); ret.setSubjectDomainPolicy(createOidType(subjectPolicyId)); return ret; } private static PolicyConstraints createPolicyConstraints(Integer inhibitPolicyMapping, Integer requireExplicitPolicy) { PolicyConstraints ret = new PolicyConstraints(); if (inhibitPolicyMapping != null) { ret.setInhibitPolicyMapping(inhibitPolicyMapping); } if (requireExplicitPolicy != null) { ret.setRequireExplicitPolicy(requireExplicitPolicy); } return ret; } private static NameConstraints createNameConstraints() { NameConstraints ret = new NameConstraints(); GeneralSubtreesType permitted = new GeneralSubtreesType(); GeneralSubtreeBaseType single = new GeneralSubtreeBaseType(); single.setDirectoryName("O=example organization, C=DE"); permitted.getBase().add(single); ret.setPermittedSubtrees(permitted); GeneralSubtreesType excluded = new GeneralSubtreesType(); single = new GeneralSubtreeBaseType(); single.setDirectoryName("OU=bad OU, O=example organization, C=DE"); excluded.getBase().add(single); ret.setExcludedSubtrees(excluded); return ret; } private static InhibitAnyPolicy createInhibitAnyPolicy(final int skipCerts) { InhibitAnyPolicy ret = new InhibitAnyPolicy(); ret.setSkipCerts(skipCerts); return ret; } private static OidWithDescType createOidType(final ASN1ObjectIdentifier oid) { return createOidType(oid, null); } private static OidWithDescType createOidType(ASN1ObjectIdentifier oid, String description) { OidWithDescType ret = new OidWithDescType(); ret.setValue(oid.getId()); if (description == null) { description = getDescription(oid); } if (description != null) { ret.setDescription(description); } return ret; } private static ExtensionValueType createConstantExtValue(final byte[] bytes) { ConstantExtValue extValue = new ConstantExtValue(); extValue.setValue(bytes); return createExtensionValueType(extValue); } private static X509ProfileType getBaseProfile(final String description, final boolean ca, final String validity, final boolean useMidnightNotBefore, String[] sigHashAlgos) { final boolean qa = false; return getBaseProfile(description, ca, qa, validity, useMidnightNotBefore, sigHashAlgos); } private static X509ProfileType getBaseProfile(final String description, final boolean ca, final boolean qa, final String validity, final boolean useMidnightNotBefore, String[] sigHashAlgos) { X509ProfileType profile = new X509ProfileType(); profile.setAppInfo(createDescription(description)); if (qa) { profile.setQaOnly(true); } profile.setCa(ca); profile.setVersion(3); profile.setValidity(validity); profile.setNotBeforeTime(useMidnightNotBefore ? "midnight" : "current"); profile.setDuplicateKey(false); profile.setDuplicateSubject(false); profile.setSerialNumberInReq(false); // SignatureAlgorithms if (sigHashAlgos != null && sigHashAlgos.length > 0) { SignatureAlgorithms sigAlgosType = new SignatureAlgorithms(); profile.setSignatureAlgorithms(sigAlgosType); List<String> l = sigAlgosType.getAlgorithm(); String[] algoPart2s = new String[] { "withRSA", "withDSA", "withECDSA", "withPlainECDSA", "withRSAandMGF1" }; for (String part2 : algoPart2s) { for (String hashAlgo : sigHashAlgos) { l.add(hashAlgo + part2); } } } // Subject Subject subject = new Subject(); profile.setSubject(subject); subject.setDnBackwards(false); // Key profile.setKeyAlgorithms(createKeyAlgorithms()); // Extensions ExtensionsType extensions = new ExtensionsType(); profile.setExtensions(extensions); return profile; } private static KeyAlgorithms createKeyAlgorithms() { KeyAlgorithms ret = new KeyAlgorithms(); List<AlgorithmType> list = ret.getAlgorithm(); // RSA { AlgorithmType algorithm = new AlgorithmType(); list.add(algorithm); algorithm.getAlgorithm().add(createOidType(PKCSObjectIdentifiers.rsaEncryption, "RSA")); RSAParameters params = new RSAParameters(); algorithm.setParameters(createKeyParametersType(params)); RangesType ranges = new RangesType(); params.setModulusLength(ranges); List<RangeType> modulusLengths = ranges.getRange(); modulusLengths.add(createRange(2048)); modulusLengths.add(createRange(3072)); } // DSA { AlgorithmType algorithm = new AlgorithmType(); list.add(algorithm); algorithm.getAlgorithm().add(createOidType(X9ObjectIdentifiers.id_dsa, "DSA")); DSAParameters params = new DSAParameters(); algorithm.setParameters(createKeyParametersType(params)); RangesType ranges = new RangesType(); params.setPLength(ranges); List<RangeType> pLengths = ranges.getRange(); pLengths.add(createRange(1024)); pLengths.add(createRange(2048)); ranges = new RangesType(); params.setQLength(ranges); List<RangeType> qLengths = ranges.getRange(); qLengths.add(createRange(160)); qLengths.add(createRange(224)); qLengths.add(createRange(256)); } // EC { AlgorithmType algorithm = new AlgorithmType(); list.add(algorithm); algorithm.getAlgorithm().add(createOidType(X9ObjectIdentifiers.id_ecPublicKey, "EC")); ECParameters params = new ECParameters(); algorithm.setParameters(createKeyParametersType(params)); Curves curves = new Curves(); params.setCurves(curves); ASN1ObjectIdentifier[] curveIds = new ASN1ObjectIdentifier[] { SECObjectIdentifiers.secp256r1, TeleTrusTObjectIdentifiers.brainpoolP256r1 }; for (ASN1ObjectIdentifier curveId : curveIds) { String name = SecurityUtil.getCurveName(curveId); curves.getCurve().add(createOidType(curveId, name)); } params.setPointEncodings(new PointEncodings()); final Byte unpressed = 4; params.getPointEncodings().getPointEncoding().add(unpressed); } return ret; } private static RangeType createRange(final int size) { return createRange(size, size); } private static RangeType createRange(final Integer min, final Integer max) { if (min == null && max == null) { throw new IllegalArgumentException("min and max can not be both null"); } RangeType range = new RangeType(); if (min != null) { range.setMin(min); } if (max != null) { range.setMax(max); } return range; } private static AnyType createDescription(final String details) { StringBuilder sb = new StringBuilder(); sb.append("<my:myDescription xmlns:my=\"http://example.org\">\n"); sb.append(" <my:category>cat A</my:category>\n"); sb.append(" <my:details>").append(details).append("</my:details>\n"); sb.append(" </my:myDescription>\n"); Element element; try { element = XMLUtil.getDocumentElment(sb.toString().getBytes()); } catch (IOException | SAXException e) { throw new RuntimeException(e.getMessage(), e); } return new ExampleDescription(element); } private static ExtensionValueType createExtensionValueType(final Object object) { ExtensionValueType ret = new ExtensionValueType(); ret.setAny(object); return ret; } private static KeyParametersType createKeyParametersType(final Object object) { KeyParametersType ret = new KeyParametersType(); ret.setAny(object); return ret; } }