package com.intrbiz.bergamot.crypto.util; import java.io.IOException; import java.security.PublicKey; import java.security.cert.Certificate; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; /** * Information about an X509 certificate in an easy to access form */ public class CertInfo { protected NameInfo subject; protected NameInfo issuer; protected int keySize; protected String keyAlg; protected String sigAlg; protected Date notBefore; protected Date notAfter; protected Set<SubjectAltName> subjectAltNames = new LinkedHashSet<SubjectAltName>(); protected CertInfo() throws IOException { super(); } public NameInfo getSubject() { return subject; } public NameInfo getIssuer() { return issuer; } public int getKeySize() { return keySize; } public String getKeyAlg() { return keyAlg; } public String getSigAlg() { return sigAlg; } public Date getNotBefore() { return notBefore; } public Date getNotAfter() { return notAfter; } public Set<SubjectAltName> getSubjectAltNames() { return Collections.unmodifiableSet(subjectAltNames); } public String toString() { return "cert-info {\n" + "subject: " + this.subject + "\n" + "issuer: " + this.issuer + "\n" + "not-before: " + this.notBefore + "\n" + "not-after: " + this.notAfter + "\n" + "key: " + this.keyAlg + " (" + this.keySize + ")\n" + "sig: " + this.sigAlg + "\n" + "subject-alt-names: " + this.subjectAltNames + "\n" + "}"; } public static CertInfo fromCertificate(Certificate cert) throws IOException { return fromX509Certificate((X509Certificate) cert); } @SuppressWarnings("restriction") public static CertInfo fromX509Certificate(X509Certificate cert) throws IOException { CertInfo info = new CertInfo(); // basic details info.sigAlg = cert.getSigAlgName(); info.notBefore = cert.getNotBefore(); info.notAfter = cert.getNotAfter(); /* * Get the subject and issuer names, we need to deal with internal classes */ info.subject = new NameInfo((sun.security.x509.X500Name) cert.getSubjectDN()); info.issuer = new NameInfo((sun.security.x509.X500Name) cert.getIssuerDN()); /* * Get some information about the key */ PublicKey key = cert.getPublicKey(); info.keyAlg = key.getAlgorithm(); if (key instanceof sun.security.rsa.RSAPublicKeyImpl) { info.keySize = ((sun.security.rsa.RSAPublicKeyImpl) key).getModulus().bitLength(); } /* * Extract the SANs */ try { /* * Yes, this really does return a collection of two element array lists! * - The first element is the Integer type of the name (2 == DNS NAME) * - The second element is the String name */ Collection<List<?>> sans = cert.getSubjectAlternativeNames(); if (sans != null) { for (List<?> san : sans) { info.subjectAltNames.add(new SubjectAltName((Integer) san.get(0), (String) san.get(1))); } } } catch (CertificateParsingException e) { throw new IOException("Error extracting SAN information", e); } return info; } }