com.yahoo.security.X509CertificateUtils Maven / Gradle / Ivy
// 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 certificateListFromPem(String pem) {
try (PEMParser parser = new PEMParser(new StringReader(pem))) {
List 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 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 getSubjectCommonNames(X509Certificate certificate) {
return getCommonNames(certificate.getSubjectX500Principal());
}
public static List getIssuerCommonNames(X509Certificate certificate) {
return getCommonNames(certificate.getIssuerX500Principal());
}
public static List 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 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);
}
}
}