package net.deterlab.abac; import java.io.*; import java.util.*; import java.security.*; import java.security.cert.*; import org.bouncycastle.asn1.*; import org.bouncycastle.asn1.util.*; import org.bouncycastle.asn1.x509.*; import org.bouncycastle.x509.*; import org.bouncycastle.jce.provider.X509AttrCertParser; import org.bouncycastle.jce.provider.X509CertificateObject; import org.bouncycastle.openssl.PEMReader; import org.bouncycastle.openssl.PEMWriter; public class Identity { private X509CertificateObject m_cert; private String m_keyid; private String m_cn; /** * Initialize internals from PEM cert in a reader. Use a PEMReader to get * the certificate, confirm it is self signed, and then the keyid and * common name. There's some work to get this stuff, but it's all an * incantation of getting the right classes to get the right data. Looks * more complex than it is. */ public void init(Reader r) throws CertificateException, NoSuchAlgorithmException,InvalidKeyException, NoSuchProviderException, SignatureException, IOException { PEMReader pr = new PEMReader(r); Object c = pr.readObject(); if (c instanceof X509CertificateObject) { m_cert = (X509CertificateObject) c; m_cert.verify(m_cert.getPublicKey()); // Cert is valid, fill in the CN and keyid // // This little rigamarole is to get to the SHA1 hash of the // key. PublicKey k = m_cert.getPublicKey(); ASN1Sequence seq = (ASN1Sequence) new ASN1InputStream( k.getEncoded()).readObject(); SubjectPublicKeyInfo ki = new SubjectPublicKeyInfo(seq); SubjectKeyIdentifier id = SubjectKeyIdentifier.createSHA1KeyIdentifier(ki); // Now format it into a string for keeps Formatter fmt = new Formatter(new StringWriter()); for (byte b: id.getKeyIdentifier()) fmt.format("%02x", b); m_keyid = fmt.out().toString(); m_cn = m_cert.getSubjectDN().getName(); /// XXX: better parse if (m_cn.startsWith("CN=")) m_cn = m_cn.substring(3); } else throw new CertificateException("Not an identity certificate"); } /** * Construct from a string, which is a filename, containing a PEM format * self signed certificate. */ public Identity(String filename) throws CertificateException, NoSuchAlgorithmException,InvalidKeyException, NoSuchProviderException, SignatureException, FileNotFoundException, IOException { init(new FileReader(filename)); } /** * Construct from a file, containing a self-signed PEM certificate. */ public Identity(File file) throws CertificateException, NoSuchAlgorithmException,InvalidKeyException, NoSuchProviderException, SignatureException, FileNotFoundException, IOException { init(new FileReader(file)); } /** * Construct from a reader, containing a self-signed PEM certificate. */ public Identity(Reader r) throws CertificateException, NoSuchAlgorithmException,InvalidKeyException, NoSuchProviderException, SignatureException, IOException { init(r); } /** * Construct from an InputStream, containing a self-signed PEM certificate. */ public Identity(InputStream s) throws CertificateException, NoSuchAlgorithmException,InvalidKeyException, NoSuchProviderException, SignatureException, IOException { init(new InputStreamReader(s)); } /** * Write the PEM cert to the given writer. */ public void write(Writer w) throws IOException { PEMWriter pw = new PEMWriter(w); pw.writeObject(m_cert); pw.close(); } /** * Write the PEM cert to a file with the given name. */ public void write(String fn) throws IOException, FileNotFoundException { write(new FileWriter(fn)); } /** * Write the PEM cert to the given file. */ public void write(File fn) throws IOException, FileNotFoundException { write(new FileWriter(fn)); } /** * Write the PEM cert to the given OutputStream. */ public void write(OutputStream s) throws IOException, FileNotFoundException { write(new OutputStreamWriter(s)); } // Accessors public String getKeyID() { return m_keyid; } public String getName() { return m_cn; } public String toString() { return m_keyid + " (" + m_cn + ")"; } public X509CertificateObject getCertificate() { return m_cert; } };