source: java/net/deterlab/abac/Identity.java @ ad24705

abac0-leakabac0-meicompt_changesgec13mei-idmei-rt0-nmei_rt0mei_rt2mei_rt2_fix_1meiyap-rt1meiyap1rt2tvf-new-xml
Last change on this file since ad24705 was 238717d, checked in by Ted Faber <faber@…>, 14 years ago

Auto-load the BouncyCastle? provider. (Makes jnlp work)

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