Index: java/net/deterlab/abac/Identity.java
===================================================================
--- java/net/deterlab/abac/Identity.java	(revision 1a7e6d35b6743a808b934ce72d45b1853308d1dc)
+++ java/net/deterlab/abac/Identity.java	(revision be05757f1e4d406274cd7d5a6a42e81181b0c726)
@@ -24,10 +24,7 @@
     /**
      *  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.
+     *  the certificate, and call init(cert) on it.
      */
-    public void init(Reader r) throws 
+    protected void init(Reader r) throws 
 	CertificateException, NoSuchAlgorithmException,InvalidKeyException,
 	NoSuchProviderException, SignatureException, IOException {
@@ -35,30 +32,26 @@
 	    Object c = pr.readObject();
 
-	    if (c instanceof X509CertificateObject) {
-		m_cert = (X509CertificateObject) c;
-		m_cert.verify(m_cert.getPublicKey());
+	    if (c instanceof X509CertificateObject) 
+		init((X509CertificateObject)c);
+	    else 
+		throw new CertificateException("Not an identity certificate");
+    }
 
-		// 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");
+    /**
+     *  Initialize internals from cert.  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.
+     */
+    protected void init(X509CertificateObject c) throws
+	CertificateException, NoSuchAlgorithmException,InvalidKeyException,
+	NoSuchProviderException, SignatureException, IOException {
+	    m_cert = (X509CertificateObject) c;
+	    m_cert.verify(m_cert.getPublicKey());
+	    // Cert is valid, fill in the CN and keyid
+	    m_keyid = extractKeyID(m_cert.getPublicKey());
+	    m_cn = m_cert.getSubjectDN().getName();
+	    /// XXX: better parse
+	    if (m_cn.startsWith("CN=")) m_cn = m_cn.substring(3);
     }
 
@@ -97,4 +90,13 @@
 	}
 
+    /**
+     * Construct from an X509CertificateObject, if you parsed one somewhere
+     * else.
+     */
+    public Identity(X509CertificateObject cert) throws 
+	CertificateException, NoSuchAlgorithmException,InvalidKeyException,
+	NoSuchProviderException, SignatureException, FileNotFoundException,
+	IOException { init(cert); }
+
 
     /**
@@ -130,4 +132,28 @@
     }
 
+    /**
+     * Get to the SHA1 hash of the key.
+     */
+    public static String extractKeyID(PublicKey k) {
+	ASN1Sequence seq = null;
+	try {
+	    seq = (ASN1Sequence) new ASN1InputStream(
+		    k.getEncoded()).readObject();
+	}
+	catch (IOException ie) {
+	    // Badly formatted key??
+	    return null;
+	}
+	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);
+	return fmt.out().toString();
+    }
+
     // Accessors
     public String getKeyID() { return m_keyid; }
