source: java/net/deterlab/abac/X509Credential.java @ 7b33c9b

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

More sane class struture

  • Property mode set to 100644
File size: 13.7 KB
Line 
1package net.deterlab.abac;
2
3import java.io.*;
4import java.math.*;
5
6import java.util.*;
7import java.security.*;
8import java.security.cert.*;
9
10import javax.security.auth.x500.*;
11
12import org.bouncycastle.asn1.*;
13import org.bouncycastle.asn1.x509.*;
14import org.bouncycastle.x509.*;
15import org.bouncycastle.x509.util.*;
16import org.bouncycastle.openssl.*;
17
18/**
19 * An ABAC credential, with or without an underlying certificate that
20 * represents it.  These are edges in proof garphs and can be constructed from
21 * their constituent Roles.
22 * @author <a href="http://abac.deterlab.net">ISI ABAC team</a>
23 * @version 1.3
24 */
25public class X509Credential extends Credential implements Comparable {
26    /** The ASN1 OID for an IETF attribute. */
27    protected static String attrOID = "1.3.6.1.5.5.7.10.4";
28    /** The ASN1 OID for AuthorityKeyIdentifier. */
29    protected static String authKeyOID = "2.5.29.35";
30    /** The certificate representing this credential */
31    protected X509V2AttributeCertificate ac;
32
33    /** Make sure BouncyCastle is loaded */
34    static { Context.loadBouncyCastle(); } 
35
36    /**
37     * Create an empty Credential.
38     */
39    public X509Credential() {
40        m_head = m_tail = null;
41        ac = null;
42        id = null;
43    }
44    /**
45     * Create a credential from a head and tail role.  This credential has no
46     * underlying certificate, and cannot be exported or used in real proofs.
47     * make_cert can create a certificate for a credential initialized this
48     * way.
49     * @param head the Role at the head of the credential
50     * @param tail the Role at the tail of the credential
51     */
52    public X509Credential(Role head, Role tail) {
53        m_head = head;
54        m_tail = tail;
55        ac = null; 
56        id = null;
57    }
58
59    /**
60     * Do the credential extraction from an input stream.  This parses the
61     * certificate from the input stream and saves it. The contents must be
62     * validated and parsed later.
63     * @param stream the InputStream to read the certificate from.
64     * @throws IOException if the stream is unparsable
65     */
66    protected void read_certificate(InputStream stream) 
67            throws IOException {
68        ac = new X509V2AttributeCertificate(stream);
69    }
70
71    /**
72     * Initialize a credential from parsed certificate.  Validiate it against
73     * the given identities and parse out the roles.  Note that catching
74     * java.security.GeneralSecurityException catches most of the exceptions
75     * this throws.
76     * @param ids a Collection of Identities to use in validating the cert
77     * @throws CertificateException if the certificate is badly formatted
78     * @throws InvalidKeyException if none of the Identities can validate the
79     *                              certificate
80     * @throws NoSuchAlgorithmException if the credential uses an unknown
81     *                              signature algorithm
82     * @throws NoSuchProviderException if the provider of the signature
83     *                              algorithm is unavailable
84     * @throws SignatureException if the signature check fails
85     */
86    protected void init(Collection<Identity> ids) 
87            throws CertificateException, InvalidKeyException, 
88                NoSuchAlgorithmException, NoSuchProviderException,
89                SignatureException {
90        for (Identity i: ids) {
91            try {
92                ac.verify(i.getCertificate().getPublicKey(), "BC");
93                id = i;
94                break;
95            }
96            catch (InvalidKeyException e) { }
97        }
98        if (id == null) throw new InvalidKeyException("Unknown identity");
99
100        load_roles();
101
102        if (!id.getKeyID().equals(m_head.principal()))
103            throw new InvalidKeyException("Unknown identity");
104    }
105
106    /**
107     * Parse a credential from an InputStream and initialize the role from it.
108     * Combine read_credential(stream) and init(ids).  Note that catching
109     * java.security.GeneralSecurityException catches most of the exceptions
110     * this throws.
111     * @param stream the InputStream to read the certificate from.
112     * @param ids a Collection of Identities to use in validating the cert
113     * @throws CertificateException if the certificate is badly formatted
114     * @throws InvalidKeyException if none of the Identities can validate the
115     *                              certificate
116     * @throws NoSuchAlgorithmException if the credential uses an unknown
117     *                              signature algorithm
118     * @throws NoSuchProviderException if the provider of the signature
119     *                              algorithm is unavailable
120     * @throws SignatureException if the signature check fails
121     * @throws IOException if the certificate is unparsable.
122     */
123    protected void init(InputStream stream, Collection<Identity> ids) 
124            throws CertificateException, InvalidKeyException, 
125                NoSuchAlgorithmException, NoSuchProviderException,
126                SignatureException, IOException {
127        read_certificate(stream);
128        if (ac == null) throw new IOException("Unknown Format");
129        init(ids);
130    }
131
132    /**
133     * Create a credential from an attribute cert in a file. Throws an
134     * exception if the cert file can't be opened or if there's a format
135     * problem with the cert.  Note that catching
136     * java.security.GeneralSecurityException catches most of the exceptions
137     * this throws.
138     * @param filename a String containing the filename to read
139     * @param ids a Collection of Identities to use in validating the cert
140     * @throws StreamParsingException if the stream is unparsable
141     * @throws CertificateException if the certificate is badly formatted
142     * @throws InvalidKeyException if none of the Identities can validate the
143     *                              certificate
144     * @throws NoSuchAlgorithmException if the credential uses an unknown
145     *                              signature algorithm
146     * @throws NoSuchProviderException if the provider of the signature
147     *                              algorithm is unavailable
148     * @throws SignatureException if the signature check fails
149     * @throws IOException if the certificate is unparsable.
150     */
151    public X509Credential(String filename, Collection<Identity> ids) 
152        throws Exception { init(new FileInputStream(filename), ids); }
153
154    /**
155     * Create a credential from an attribute cert in a file. Throws an
156     * exception if the cert file can't be opened or if there's a format
157     * problem with the cert.  Note that catching
158     * java.security.GeneralSecurityException catches most of the exceptions
159     * this throws.
160     * @param file the File to read
161     * @param ids a Collection of Identities to use in validating the cert
162     * @throws StreamParsingException if the stream is unparsable
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.
172     */
173    public X509Credential(File file, Collection<Identity> ids) 
174            throws CertificateException, InvalidKeyException, 
175                NoSuchAlgorithmException, NoSuchProviderException,
176                SignatureException, StreamParsingException, IOException {
177        init(new FileInputStream(file), ids);
178    }
179
180    /**
181     * Create a credential from an InputStream.  Throws an exception if the
182     * stream can't be parsed or if there's a format problem with the cert.
183     * Note that catching java.security.GeneralSecurityException catches most
184     * of the exceptions this throws.
185     * @param s the InputStream to read
186     * @param ids a Collection of Identities to use in validating the cert
187     * @throws StreamParsingException if the stream is unparsable
188     * @throws CertificateException if the certificate is badly formatted
189     * @throws InvalidKeyException if none of the Identities can validate the
190     *                              certificate
191     * @throws NoSuchAlgorithmException if the credential uses an unknown
192     *                              signature algorithm
193     * @throws NoSuchProviderException if the provider of the signature
194     *                              algorithm is unavailable
195     * @throws SignatureException if the signature check fails
196     * @throws IOException if the certificate is unparsable.
197     */
198    public X509Credential(InputStream s, Collection<Identity> ids) 
199            throws CertificateException, InvalidKeyException, 
200                NoSuchAlgorithmException, NoSuchProviderException,
201                SignatureException, StreamParsingException, IOException {
202        init(s, ids);
203    }
204
205    /**
206     * Create a credential from an X509V2AttributeCertificate object.  Throws
207     * an exception if the certificate doesn't parse into an ABAC credential,
208     * or cannot be validated.  Note that catching
209     * java.security.GeneralSecurityException catches most of the exceptions
210     * this throws.
211     * @param c the X509V2AttributeCertificate to create from
212     * @param ids a Collection of Identities to use in validating the cert
213     * @throws CertificateException if the certificate is badly formatted
214     * @throws InvalidKeyException if none of the Identities can validate the
215     *                              certificate
216     * @throws NoSuchAlgorithmException if the credential uses an unknown
217     *                              signature algorithm
218     * @throws NoSuchProviderException if the provider of the signature
219     *                              algorithm is unavailable
220     * @throws SignatureException if the signature check fails
221     * @throws IOException if the certificate is unparsable.
222     */
223    public X509Credential(X509V2AttributeCertificate c, Collection<Identity> ids) 
224            throws CertificateException, InvalidKeyException, 
225                NoSuchAlgorithmException, NoSuchProviderException,
226                SignatureException, IOException {
227        ac = c;
228        init(ids);
229    }
230
231
232    /**
233     * Create a certificate from this credential issued by the given identity.
234     * Note that catching java.security.GeneralSecurityException catches most
235     * of the exceptions this throws.
236     * @param i the Identity that will issue the certificate
237     * @throws IOException reading or writing problems
238     * @throws CertificateEncodingException Problem creating certificate
239     * @throws InvalidKeyException if none of the Identities can sign the
240     *                              certificate
241     * @throws NoSuchAlgorithmException if the credential uses an unknown
242     *                              signature algorithm
243     * @throws NoSuchProviderException if the provider of the signature
244     *                              algorithm is unavailable
245     * @throws SignatureException if the signature creation fails
246     */
247    public void make_cert(Identity i) 
248            throws IOException, CertificateEncodingException,
249               NoSuchProviderException, NoSuchAlgorithmException,
250               SignatureException, InvalidKeyException {
251        PrivateKey key = i.getKeyPair().getPrivate();
252        SubjectPublicKeyInfo pki = Context.extractSubjectPublicKeyInfo(
253                i.getKeyPair().getPublic());
254        X509V2AttributeCertificateGenerator gen = 
255            new X509V2AttributeCertificateGenerator();
256
257        gen.setIssuer(new AttributeCertificateIssuer(
258                    new X500Principal("CN="+m_head.principal())));
259        gen.setHolder(new AttributeCertificateHolder(
260                    new X500Principal("CN="+m_head.principal())));
261        gen.setNotAfter(new Date(System.currentTimeMillis() 
262                    + (3600L * 1000L * 24L * 365L)));
263        gen.setNotBefore(new Date(System.currentTimeMillis()));
264        gen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
265        gen.addAttribute(new X509Attribute(attrOID, 
266                    new DERSequence(
267                        new DERSequence(
268                            new DERUTF8String(toString())))));
269        gen.setSignatureAlgorithm("SHA256WithRSAEncryption");
270
271        // Creddy expects an authority key identifier.
272        gen.addExtension(authKeyOID, false, 
273                new AuthorityKeyIdentifier(pki));
274        // Create the cert.
275        ac = (X509V2AttributeCertificate) gen.generate(key, "BC");
276        id = i;
277    }
278
279    /**
280     * Load the roles off the attribute cert. Throws a RuntimeException if
281     * there's something wrong with the cert.
282     */
283    private void load_roles() {
284        String roles = null;
285        try {
286            X509Attribute attr = ac.getAttributes()[0];
287
288            DERSequence    t1     = (DERSequence)attr.getValues()[0];
289            DERSequence    t2  = (DERSequence)t1.getObjectAt(0);
290            DERUTF8String  t3    = (DERUTF8String)t2.getObjectAt(0);
291
292            roles = t3.getString();
293        }
294        catch (Exception e) {
295            throw new RuntimeException("Badly formatted certificate");
296        }
297
298        String[] parts = roles.split("\\s*<--?\\s*");
299        if (parts.length != 2)
300            throw new RuntimeException("Invalid attribute: " + roles);
301
302        m_head = new Role(parts[0]);
303        m_tail = new Role(parts[1]);
304    }
305
306    /**
307     * Gets the cert associated with this credential (if any).
308     * @return the attribute cert associated with this credential (if any).
309     */
310    public X509V2AttributeCertificate cert() { return ac; }
311
312    /**
313     * Output the DER formatted attribute certificate associated with this
314     * Credential to the OutputStream.
315     * @param s the OutputStream on which to write
316     * @throws IOException if there is an error writing.
317     */
318    public void write(OutputStream s) throws IOException {
319        if (ac != null ) 
320            s.write(ac.getEncoded());
321        s.flush();
322    }
323
324    /**
325     * Output the DER formatted attribute certificate associated with this
326     * Credential to the filename given.
327     * @param fn a String containing the output filename
328     * @throws IOException if there is an error writing.
329     */
330    public void write(String fn) throws IOException, FileNotFoundException {
331        write(new FileOutputStream(fn));
332    }
333
334    /**
335     * Return true if this Credential has a certificate associated.  A jabac
336     * extension.
337     * @return true if this Credential has a certificate associated.
338     */
339    public boolean hasCertificate() { return ac != null; }
340
341    /**
342     * Return the X509V2AttributeCertificate that underlys the Credential
343     * @return the X509V2AttributeCertificate that underlys the Credential.
344     */
345    public X509V2AttributeCertificate attributeCert() { return ac; }
346
347
348}
Note: See TracBrowser for help on using the repository browser.