diff options
author | Bjørn Christian Seime <bjorncs@oath.com> | 2018-10-17 16:21:59 +0200 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@oath.com> | 2018-10-17 16:21:59 +0200 |
commit | 19ca55a3bb4e308ef1122a1cdd8c911b811e18be (patch) | |
tree | 17aa598f52f0034d2246babe749796923e90a7bf /security-utils/src/main/java/com/yahoo/security/X509CertificateUtils.java | |
parent | 39da869d94cebe5bd851e1b4fb456372586a6870 (diff) |
Move classes in com.yahoo.security to security-utils
Diffstat (limited to 'security-utils/src/main/java/com/yahoo/security/X509CertificateUtils.java')
-rw-r--r-- | security-utils/src/main/java/com/yahoo/security/X509CertificateUtils.java | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/security-utils/src/main/java/com/yahoo/security/X509CertificateUtils.java b/security-utils/src/main/java/com/yahoo/security/X509CertificateUtils.java new file mode 100644 index 00000000000..33bd750bac5 --- /dev/null +++ b/security-utils/src/main/java/com/yahoo/security/X509CertificateUtils.java @@ -0,0 +1,136 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.security; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.x509.GeneralNames; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.openssl.PEMParser; +import org.bouncycastle.openssl.jcajce.JcaPEMWriter; +import org.bouncycastle.util.io.pem.PemObject; + +import javax.naming.NamingException; +import javax.naming.ldap.LdapName; +import javax.security.auth.x500.X500Principal; +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.UncheckedIOException; +import java.security.GeneralSecurityException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static com.yahoo.security.Extension.SUBJECT_ALTERNATIVE_NAMES; +import static java.util.stream.Collectors.toList; + +/** + * @author bjorncs + */ +public class X509CertificateUtils { + + private X509CertificateUtils() {} + + public static X509Certificate fromPem(String pem) { + try (PEMParser parser = new PEMParser(new StringReader(pem))) { + return toX509Certificate(parser.readObject()); + } catch (IOException e) { + throw new UncheckedIOException(e); + } catch (CertificateException e) { + throw new RuntimeException(e); + } + } + + public static List<X509Certificate> certificateListFromPem(String pem) { + try (PEMParser parser = new PEMParser(new StringReader(pem))) { + List<X509Certificate> list = new ArrayList<>(); + Object pemObject; + while ((pemObject = parser.readObject()) != null) { + list.add(toX509Certificate(pemObject)); + } + return list; + } catch (IOException e) { + throw new UncheckedIOException(e); + } catch (CertificateException e) { + throw new RuntimeException(e); + } + } + + private static X509Certificate toX509Certificate(Object pemObject) throws CertificateException { + if (pemObject instanceof X509Certificate) { + return (X509Certificate) pemObject; + } + if (pemObject instanceof X509CertificateHolder) { + return new JcaX509CertificateConverter() + .setProvider(BouncyCastleProviderHolder.getInstance()) + .getCertificate((X509CertificateHolder) pemObject); + } + throw new IllegalArgumentException("Invalid type of PEM object: " + pemObject); + } + + public static String toPem(X509Certificate certificate) { + try (StringWriter stringWriter = new StringWriter(); JcaPEMWriter pemWriter = new JcaPEMWriter(stringWriter)) { + pemWriter.writeObject(new PemObject("CERTIFICATE", certificate.getEncoded())); + pemWriter.flush(); + return stringWriter.toString(); + } catch (GeneralSecurityException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public static String toPem(List<X509Certificate> certificates) { + try (StringWriter stringWriter = new StringWriter(); JcaPEMWriter pemWriter = new JcaPEMWriter(stringWriter)) { + for (X509Certificate certificate : certificates) { + pemWriter.writeObject(new PemObject("CERTIFICATE", certificate.getEncoded())); + } + pemWriter.flush(); + return stringWriter.toString(); + } catch (GeneralSecurityException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public static List<String> getSubjectCommonNames(X509Certificate certificate) { + return getCommonNames(certificate.getSubjectX500Principal()); + } + + public static List<String> getIssuerCommonNames(X509Certificate certificate) { + return getCommonNames(certificate.getIssuerX500Principal()); + } + + public static List<String> getCommonNames(X500Principal subject) { + try { + String subjectPrincipal = subject.getName(); + return new LdapName(subjectPrincipal).getRdns().stream() + .filter(rdn -> rdn.getType().equalsIgnoreCase("cn")) + .map(rdn -> rdn.getValue().toString()) + .collect(toList()); + } catch (NamingException e) { + throw new IllegalArgumentException("Invalid CN: " + e, e); + } + + } + + public static List<SubjectAlternativeName> getSubjectAlternativeNames(X509Certificate certificate) { + try { + byte[] extensionValue = certificate.getExtensionValue(SUBJECT_ALTERNATIVE_NAMES.getOId()); + if (extensionValue == null) return Collections.emptyList(); + ASN1Encodable asn1Encodable = ASN1Primitive.fromByteArray(extensionValue); + if (asn1Encodable instanceof ASN1OctetString) { + asn1Encodable = ASN1Primitive.fromByteArray(((ASN1OctetString) asn1Encodable).getOctets()); + } + GeneralNames names = GeneralNames.getInstance(asn1Encodable); + return SubjectAlternativeName.fromGeneralNames(names); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } +} |