source: java/net/deterlab/abac/Identity.java @ 7f614c1

abac0-leakabac0-meimei-idmei-rt0-nmei_rt0tvf-new-xml
Last change on this file since 7f614c1 was a7f73b5, checked in by Ted Faber <faber@…>, 12 years ago

Document cleanup. Change a few visibilities.

  • Property mode set to 100644
File size: 13.3 KB
RevLine 
[9725efb]1package net.deterlab.abac;
2
3import java.io.*;
4
5import java.util.*;
6import java.security.*;
7import java.security.cert.*;
[3a52bed]8import javax.security.auth.x500.*;
[9725efb]9
[3a52bed]10import java.math.BigInteger;
[9725efb]11
12import org.bouncycastle.asn1.*;
13import org.bouncycastle.asn1.util.*;
14import org.bouncycastle.asn1.x509.*;
15import org.bouncycastle.x509.*;
[238717d]16import org.bouncycastle.openssl.*;
17
[9725efb]18
[e36ea1d]19/**
20 * An ABAC identity.  An X509 Certificate-encoded public key.  The key
21 * identifier is used as the name of the Identity.  This whole class is
22 * something of a jabac extension.
23 * @author <a href="http://abac.deterlab.net">ISI ABAC team</a>
[4560b65]24 * @version 1.4
[e36ea1d]25 */
[5cf72cc]26public class Identity implements Comparable {
[e36ea1d]27    /** The underlying X509 certificate. */
28    protected X509Certificate cert;
29    /** The public key id used as this principal's name */
30    protected String keyid;
31    /** The common name in the certificate, used as a mnemonic */
32    protected String cn;
33    /** The keypair, if any, used to sign for this Identity */
34    protected KeyPair kp;
[9725efb]35
[238717d]36    /** Make sure BouncyCastle is loaded */
37    static { Context.loadBouncyCastle(); } 
38
[1a7e6d3]39    /**
[e36ea1d]40     * Initialize from PEM cert in a reader.  Use a PEMReader to get
41     * the certificate, and call init(cert) on it.
42     * @param r a Reader containing the certificate
43     * @throws CertificateException if the certificate is badly formatted
44     * @throws InvalidKeyException if none of the Identities can validate the
45     *                              certificate
46     * @throws NoSuchAlgorithmException if the credential uses an unknown
47     *                              signature algorithm
48     * @throws NoSuchProviderException if the provider of the signature
49     *                              algorithm is unavailable
50     * @throws SignatureException if the signature check fails
51     * @throws IOException if the certificate is unparsable.
[1a7e6d3]52     */
[8a14e37]53    protected void init(Reader r) throws 
[42ca4b8]54            CertificateException, NoSuchAlgorithmException,InvalidKeyException,
55            NoSuchProviderException, SignatureException, IOException {
56        PEMReader pr = new PEMReader(r);
57        Object c = null;
58
59        while ( ( c= pr.readObject()) != null ){
60
[84f0e7a]61            if (c instanceof X509Certificate) {
[0595372]62                if ( cn == null ) 
[84f0e7a]63                    init((X509Certificate)c);
[42ca4b8]64                else
65                    throw new CertificateException("Two certs in one file");
66            }
67            else if (c instanceof KeyPair) setKeyPair((KeyPair)c);
[8a14e37]68            else 
[42ca4b8]69                throw new CertificateException(
70                        "Not an identity certificate");
71        }
[f31432f]72        // If there's nothing for the PEM reader to parse, the cert is invalid.
73        if (cn == null) 
74            throw new CertificateException(
75                    "Not an identity certificate");
[8a14e37]76    }
77
78    /**
[e36ea1d]79     * Initialize internals from cert.  Confirm it is self signed,  and then
80     * the keyid and common name.  There's some work to get this stuff, but
81     * it's all an incantation of getting the right classes to get the right
82     * data.  Looks more complex than it is.
83     * @param c an X509Certificate to init from
84     * @throws CertificateException if the certificate is badly formatted
85     * @throws InvalidKeyException if none of the Identities can validate the
86     *                              certificate
87     * @throws NoSuchAlgorithmException if the credential uses an unknown
88     *                              signature algorithm
89     * @throws NoSuchProviderException if the provider of the signature
90     *                              algorithm is unavailable
91     * @throws SignatureException if the signature check fails
92     * @throws IOException if the certificate is unparsable.
[8a14e37]93     */
[84f0e7a]94    protected void init(X509Certificate c) throws
[8a14e37]95        CertificateException, NoSuchAlgorithmException,InvalidKeyException,
96        NoSuchProviderException, SignatureException, IOException {
[0595372]97            cert = (X509Certificate) c;
98            cert.verify(cert.getPublicKey());
[8a14e37]99            // Cert is valid, fill in the CN and keyid
[0595372]100            keyid = Context.extractKeyID(cert.getPublicKey());
101            cn = cert.getSubjectDN().getName();
[8a14e37]102            /// XXX: better parse
[0595372]103            if (cn.startsWith("CN=")) cn = cn.substring(3);
[9725efb]104    }
105
[1a7e6d3]106    /**
[e36ea1d]107     * Construct from a string, used as a CN.  Keys are generated.
108     * @param cn a String containing the menomnic name
109     * @throws IOException reading or writing problems
110     * @throws CertificateEncodingException Problem creating certificate
111     * @throws InvalidKeyException if none of the Identities can sign the
112     *                              certificate
113     * @throws NoSuchAlgorithmException if the credential uses an unknown
114     *                              signature algorithm
115     * @throws NoSuchProviderException if the provider of the signature
116     *                              algorithm is unavailable
117     * @throws SignatureException if the signature creation fails
[1a7e6d3]118     */
[3a52bed]119    public Identity(String cn) throws
120            CertificateException, NoSuchAlgorithmException,InvalidKeyException,
121            NoSuchProviderException, SignatureException, IOException {
122        X509V1CertificateGenerator gen = new X509V1CertificateGenerator();
[42ca4b8]123        kp = KeyPairGenerator.getInstance("RSA").genKeyPair();
[3a52bed]124
125        gen.setIssuerDN(new X500Principal("CN=" + cn));
126        gen.setSubjectDN(new X500Principal("CN=" + cn));
127        gen.setNotAfter(new Date(System.currentTimeMillis() 
[9d2b1bc]128                    + (3600L * 1000L * 24L * 365L)));
[3a52bed]129        gen.setNotBefore(new Date(System.currentTimeMillis()));
130        gen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
131        gen.setPublicKey(kp.getPublic());
132        gen.setSignatureAlgorithm("SHA256WithRSAEncryption");
[238717d]133        X509Certificate a = (X509Certificate) gen.generate(kp.getPrivate(), "BC");
[3a52bed]134        init(a);
135    }
136
[9725efb]137
138
[1a7e6d3]139    /**
[a7f73b5]140     * Construct from a file containing a self-signed PEM certificate.
[e36ea1d]141     * @param file the File to read
142     * @throws CertificateException if the certificate is badly formatted
143     * @throws InvalidKeyException if none of the Identities can validate the
144     *                              certificate
145     * @throws NoSuchAlgorithmException if the credential uses an unknown
146     *                              signature algorithm
147     * @throws NoSuchProviderException if the provider of the signature
148     *                              algorithm is unavailable
149     * @throws SignatureException if the signature check fails
150     * @throws IOException if the certificate is unparsable.
[1a7e6d3]151     */
[9725efb]152    public Identity(File file) throws 
153        CertificateException, NoSuchAlgorithmException,InvalidKeyException,
154        NoSuchProviderException, SignatureException, FileNotFoundException,
[42ca4b8]155        IOException { 
156            kp = null;
157            init(new FileReader(file));
158        }
[1a7e6d3]159
160    /**
[e36ea1d]161     * Construct from a reader containing a self-signed PEM certificate.
162     * @param r the Reader containing the certificate
163     * @throws CertificateException if the certificate is badly formatted
164     * @throws InvalidKeyException if none of the Identities can validate the
165     *                              certificate
166     * @throws NoSuchAlgorithmException if the credential uses an unknown
167     *                              signature algorithm
168     * @throws NoSuchProviderException if the provider of the signature
169     *                              algorithm is unavailable
170     * @throws SignatureException if the signature check fails
171     * @throws IOException if the certificate is unparsable.
[1a7e6d3]172     */
173    public Identity(Reader r) throws 
174        CertificateException, NoSuchAlgorithmException,InvalidKeyException,
[42ca4b8]175        NoSuchProviderException, SignatureException, IOException {
176            kp = null;
177            init(r);
178        }
[1a7e6d3]179
180    /**
[e36ea1d]181     * Construct from an InputStream containing a self-signed PEM certificate.
182     * @param s the InputStream containing the certificate
183     * @throws CertificateException if the certificate is badly formatted
184     * @throws InvalidKeyException if none of the Identities can validate the
185     *                              certificate
186     * @throws NoSuchAlgorithmException if the credential uses an unknown
187     *                              signature algorithm
188     * @throws NoSuchProviderException if the provider of the signature
189     *                              algorithm is unavailable
190     * @throws SignatureException if the signature check fails
191     * @throws IOException if the certificate is unparsable.
[1a7e6d3]192     */
193    public Identity(InputStream s) throws 
194        CertificateException, NoSuchAlgorithmException,InvalidKeyException,
195        NoSuchProviderException, SignatureException, IOException { 
[42ca4b8]196            kp = null;
[1a7e6d3]197            init(new InputStreamReader(s));
198        }
199
[8a14e37]200    /**
[e36ea1d]201     * Construct from an X509Certificate
202     * @param cert an X509Certificate to init from
203     * @throws CertificateException if the certificate is badly formatted
204     * @throws InvalidKeyException if none of the Identities can validate the
205     *                              certificate
206     * @throws NoSuchAlgorithmException if the credential uses an unknown
207     *                              signature algorithm
208     * @throws NoSuchProviderException if the provider of the signature
209     *                              algorithm is unavailable
210     * @throws SignatureException if the signature check fails
211     * @throws IOException if the certificate is unparsable.
[8a14e37]212     */
[84f0e7a]213    public Identity(X509Certificate cert) throws 
[8a14e37]214        CertificateException, NoSuchAlgorithmException,InvalidKeyException,
215        NoSuchProviderException, SignatureException, FileNotFoundException,
[42ca4b8]216        IOException { 
217            kp = null;
218            init(cert);
219        }
[8a14e37]220
[8a93b41]221    /**
222     * Write the PEM key to the given writer.
[e36ea1d]223     * @param w the Writer
224     * @return true if the Identity had a keypair and wrote the key
225     * @throws IOException if writing fails
[8a93b41]226     */
227    public boolean writePrivateKey(Writer w) throws IOException {
228        if (kp != null ) {
229            PEMWriter pw = new PEMWriter(w);
230
231            pw.writeObject(kp.getPrivate());
232            pw.flush();
233            return true;
234        }
235        else return false;
236    }
237
238    /**
239     * Write the PEM key to a file with the given name.
240     */
241    public boolean writePrivateKey(String fn) 
242            throws IOException, FileNotFoundException {
243        return writePrivateKey(new FileWriter(fn));
244    }
245
246    /**
247     * Write the PEM key to the given file.
[e36ea1d]248     * @param fn a String with the output file name
249     * @return true if the Identity had a keypair and wrote the key
250     * @throws IOException if writing fails
[8a93b41]251     */
252    public boolean writePrivateKey(File fn) 
253            throws IOException, FileNotFoundException {
254        return writePrivateKey(new FileWriter(fn));
255    }
256
257    /**
258     * Write the PEM key to the given OutputStream.
[e36ea1d]259     * @param s an OutputStream to write on
260     * @return true if the Identity had a keypair and wrote the key
261     * @throws IOException if writing fails
[8a93b41]262     */
263    public boolean writePrivateKey(OutputStream s) 
264            throws IOException, FileNotFoundException {
265        return writePrivateKey(new OutputStreamWriter(s));
266    }
267
[1a7e6d3]268
269    /**
270     * Write the PEM cert to the given writer.
[e36ea1d]271     * @param w a Writer to write on
272     * @throws IOException if writing fails
[1a7e6d3]273     */
274    public void write(Writer w) throws IOException {
275        PEMWriter pw = new PEMWriter(w);
276
[0595372]277        pw.writeObject(cert);
[5cf72cc]278        pw.flush();
[1a7e6d3]279    }
280
281    /**
282     * Write the PEM cert to a file with the given name.
283     */
284    public void write(String fn) throws IOException, FileNotFoundException {
285        write(new FileWriter(fn));
286    }
287
288    /**
289     * Write the PEM cert to the given file.
[e36ea1d]290     * @param fn a String with the output file name
291     * @throws IOException if writing fails
[1a7e6d3]292     */
293    public void write(File fn) throws IOException, FileNotFoundException {
294        write(new FileWriter(fn));
295    }
296
297    /**
298     * Write the PEM cert to the given OutputStream.
[e36ea1d]299     * @param s an OutputStream to write on
300     * @throws IOException if writing fails
[1a7e6d3]301     */
302    public void write(OutputStream s) 
303        throws IOException, FileNotFoundException {
304        write(new OutputStreamWriter(s));
305    }
[9725efb]306
[e9360e2]307
[e36ea1d]308    /**
309     * Return the Identity's KeyID
310     * @return the Identity's KeyID
311     */
[0595372]312    public String getKeyID() { return keyid; }
[e36ea1d]313    /**
314     * Return the Identity's mnemonic name
315     * @return the Identity's mnemonic name
316     */
[0595372]317    public String getName() { return cn; }
[e36ea1d]318    /**
319     * Return the Identity's X509 Certificate
320     * @return the Identity's X509 Certificate
321     */
322    public X509Certificate getCertificate() { return cert; }
323    /**
324     * Return a simple string rep of the Identity.
325     * @return a simple string rep of the Identity.
326     */
[42ca4b8]327    public String toString() { 
[0595372]328        String s = keyid + " (" + cn ;
[42ca4b8]329
[0595372]330        if (keyid != null ) s += " [keyed]";
[42ca4b8]331        s += ")";
332        return s;
333    }
334    /**
335     * Associate a keypair with this Identity.  If the ID has a certificate,
336     * make sure that the keypair matches it.  If not throw an
337     * IllegalArgumentException.
[e36ea1d]338     * @param k the KeyPair to connect
339     * @throws IllegalArgumentException if the keypair does not
340     *                              match the pubkey in the X509 certificate
[42ca4b8]341     */
342    public void setKeyPair(KeyPair k) {
[0595372]343        if (keyid != null) {
344            String kid = Context.extractKeyID(k.getPublic());
[42ca4b8]345
[0595372]346            if ( kid != null && kid.equals(keyid)) kp = k;
[42ca4b8]347            else 
348                throw new IllegalArgumentException(
349                        "Keypair does not match certificate");
350        }
351        else kp = k;
352    }
[e36ea1d]353
354    /**
355     * Return the keypair associated with this Identity (if any)
356     * @return the keypair associated with this Identity (if any)
357     */
[42ca4b8]358    public KeyPair getKeyPair() { return kp; }
[e36ea1d]359
360    /**
[a7f73b5]361     * Return true if the two identites refer to teh same key.  Two Identities
362     * are equal if their key ID's match.
[e36ea1d]363     * @return true if the two key ID's are equal.
364     */
[5cf72cc]365    public boolean equals(Object o) { 
366        if ( o == null ) return false;
367        else if ( ! (o instanceof Identity) ) return false;
368        else return getKeyID().equals(((Identity)o).getKeyID());
369    }
[e36ea1d]370    /**
[a7f73b5]371     * Order 2 identities for sorting.  They are ordered by their key ID's.
[e36ea1d]372     * @param o an Object to compare
373     * @return -1 if this Identity is before, 0 if they are the same, and 1
374     *              if this Identity is after the given object.
375     */
[5cf72cc]376    public int compareTo(Object o) { 
377        if ( ! (o instanceof Identity) ) return 1;
378        else return getKeyID().compareTo(((Identity)o).getKeyID());
379    }
[1a7e6d3]380
[9725efb]381};
Note: See TracBrowser for help on using the repository browser.