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

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

Credential compatibility with libcreddy. Creddy expects an X509 extension identifying the key used to sign an attribute credential.

  • Property mode set to 100644
File size: 8.0 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.jce.provider.X509AttrCertParser;
17import org.bouncycastle.jce.provider.X509CertificateObject;
18import org.bouncycastle.openssl.PEMReader;
19import org.bouncycastle.openssl.PEMWriter;
20
21public class Identity implements Comparable {
22    private X509CertificateObject m_cert;
23    private String m_keyid;
24    private String m_cn;
25    private KeyPair kp;
26
27    /**
28     *  Initialize internals from PEM cert in a reader.  Use a PEMReader to get
29     *  the certificate, and call init(cert) on it.
30     */
31    protected void init(Reader r) throws 
32            CertificateException, NoSuchAlgorithmException,InvalidKeyException,
33            NoSuchProviderException, SignatureException, IOException {
34        PEMReader pr = new PEMReader(r);
35        Object c = null;
36
37        while ( ( c= pr.readObject()) != null ){
38
39            if (c instanceof X509CertificateObject) {
40                if ( m_cn == null ) 
41                    init((X509CertificateObject)c);
42                else
43                    throw new CertificateException("Two certs in one file");
44            }
45            else if (c instanceof KeyPair) setKeyPair((KeyPair)c);
46            else 
47                throw new CertificateException(
48                        "Not an identity certificate");
49        }
50    }
51
52    /**
53     *  Initialize internals from cert.  Confirm it is self signed,  and then
54     *  the keyid and common name.  There's some work to get this stuff, but
55     *  it's all an incantation of getting the right classes to get the right
56     *  data.  Looks more complex than it is.
57     */
58    protected void init(X509CertificateObject c) throws
59        CertificateException, NoSuchAlgorithmException,InvalidKeyException,
60        NoSuchProviderException, SignatureException, IOException {
61            m_cert = (X509CertificateObject) c;
62            m_cert.verify(m_cert.getPublicKey());
63            // Cert is valid, fill in the CN and keyid
64            m_keyid = extractKeyID(m_cert.getPublicKey());
65            m_cn = m_cert.getSubjectDN().getName();
66            /// XXX: better parse
67            if (m_cn.startsWith("CN=")) m_cn = m_cn.substring(3);
68    }
69
70    /**
71     * Construct from a string, used as a CN
72     */
73    public Identity(String cn) throws
74            CertificateException, NoSuchAlgorithmException,InvalidKeyException,
75            NoSuchProviderException, SignatureException, IOException {
76        X509V1CertificateGenerator gen = new X509V1CertificateGenerator();
77        kp = KeyPairGenerator.getInstance("RSA").genKeyPair();
78
79        gen.setIssuerDN(new X500Principal("CN=" + cn));
80        gen.setSubjectDN(new X500Principal("CN=" + cn));
81        gen.setNotAfter(new Date(System.currentTimeMillis() 
82                    + 3600 * 1000 * 24 * 365));
83        gen.setNotBefore(new Date(System.currentTimeMillis()));
84        gen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
85        gen.setPublicKey(kp.getPublic());
86        gen.setSignatureAlgorithm("SHA256WithRSAEncryption");
87        X509CertificateObject a = 
88            (X509CertificateObject) gen.generate(kp.getPrivate());
89        init(a);
90    }
91
92
93
94    /**
95     * Construct from a file, containing a self-signed PEM certificate.
96     */
97    public Identity(File file) throws 
98        CertificateException, NoSuchAlgorithmException,InvalidKeyException,
99        NoSuchProviderException, SignatureException, FileNotFoundException,
100        IOException { 
101            kp = null;
102            init(new FileReader(file));
103        }
104
105    /**
106     * Construct from a reader, containing a self-signed PEM certificate.
107     */
108    public Identity(Reader r) throws 
109        CertificateException, NoSuchAlgorithmException,InvalidKeyException,
110        NoSuchProviderException, SignatureException, IOException {
111            kp = null;
112            init(r);
113        }
114
115    /**
116     * Construct from an InputStream, containing a self-signed PEM certificate.
117     */
118    public Identity(InputStream s) throws 
119        CertificateException, NoSuchAlgorithmException,InvalidKeyException,
120        NoSuchProviderException, SignatureException, IOException { 
121            kp = null;
122            init(new InputStreamReader(s));
123        }
124
125    /**
126     * Construct from an X509CertificateObject, if you parsed one somewhere
127     * else.
128     */
129    public Identity(X509CertificateObject cert) throws 
130        CertificateException, NoSuchAlgorithmException,InvalidKeyException,
131        NoSuchProviderException, SignatureException, FileNotFoundException,
132        IOException { 
133            kp = null;
134            init(cert);
135        }
136
137    /**
138     * Write the PEM key to the given writer.
139     */
140    public boolean writePrivateKey(Writer w) throws IOException {
141        if (kp != null ) {
142            PEMWriter pw = new PEMWriter(w);
143
144            pw.writeObject(kp.getPrivate());
145            pw.flush();
146            return true;
147        }
148        else return false;
149    }
150
151    /**
152     * Write the PEM key to a file with the given name.
153     */
154    public boolean writePrivateKey(String fn) 
155            throws IOException, FileNotFoundException {
156        return writePrivateKey(new FileWriter(fn));
157    }
158
159    /**
160     * Write the PEM key to the given file.
161     */
162    public boolean writePrivateKey(File fn) 
163            throws IOException, FileNotFoundException {
164        return writePrivateKey(new FileWriter(fn));
165    }
166
167    /**
168     * Write the PEM key to the given OutputStream.
169     */
170    public boolean writePrivateKey(OutputStream s) 
171            throws IOException, FileNotFoundException {
172        return writePrivateKey(new OutputStreamWriter(s));
173    }
174
175
176    /**
177     * Write the PEM cert to the given writer.
178     */
179    public void write(Writer w) throws IOException {
180        PEMWriter pw = new PEMWriter(w);
181
182        pw.writeObject(m_cert);
183        pw.flush();
184    }
185
186    /**
187     * Write the PEM cert to a file with the given name.
188     */
189    public void write(String fn) throws IOException, FileNotFoundException {
190        write(new FileWriter(fn));
191    }
192
193    /**
194     * Write the PEM cert to the given file.
195     */
196    public void write(File fn) throws IOException, FileNotFoundException {
197        write(new FileWriter(fn));
198    }
199
200    /**
201     * Write the PEM cert to the given OutputStream.
202     */
203    public void write(OutputStream s) 
204        throws IOException, FileNotFoundException {
205        write(new OutputStreamWriter(s));
206    }
207
208
209    /**
210     * Get to the SHA1 hash of the key.
211     */
212    public static String extractKeyID(PublicKey k) {
213        SubjectPublicKeyInfo ki = extractSubjectPublicKeyInfo(k);
214        SubjectKeyIdentifier id = 
215            SubjectKeyIdentifier.createSHA1KeyIdentifier(ki);
216
217        // Now format it into a string for keeps
218        Formatter fmt = new Formatter(new StringWriter());
219        for (byte b: id.getKeyIdentifier())
220            fmt.format("%02x", b);
221        return fmt.out().toString();
222    }
223
224    /**
225     * Extratct the SubjectPublicKeyInfo.  Useful for some other encryptions,
226     * notably Certificate.make_cert().
227     */
228    public static SubjectPublicKeyInfo extractSubjectPublicKeyInfo(PublicKey k) {
229        ASN1Sequence seq = null;
230        try {
231            seq = (ASN1Sequence) new ASN1InputStream(
232                    k.getEncoded()).readObject();
233        }
234        catch (IOException ie) {
235            // Badly formatted key??
236            return null;
237        }
238        return new SubjectPublicKeyInfo(seq);
239    }
240
241
242    // Accessors
243    public String getKeyID() { return m_keyid; }
244    public String getName() { return m_cn; }
245    public String toString() { 
246        String s = m_keyid + " (" + m_cn ;
247
248        if (m_keyid != null ) s += " [keyed]";
249        s += ")";
250        return s;
251    }
252    /**
253     * Associate a keypair with this Identity.  If the ID has a certificate,
254     * make sure that the keypair matches it.  If not throw an
255     * IllegalArgumentException.
256     */
257    public void setKeyPair(KeyPair k) {
258        if (m_keyid != null) {
259            String kid = extractKeyID(k.getPublic());
260
261            if ( kid != null && kid.equals(m_keyid)) kp = k;
262            else 
263                throw new IllegalArgumentException(
264                        "Keypair does not match certificate");
265        }
266        else kp = k;
267    }
268    public KeyPair getKeyPair() { return kp; }
269    public boolean equals(Object o) { 
270        if ( o == null ) return false;
271        else if ( ! (o instanceof Identity) ) return false;
272        else return getKeyID().equals(((Identity)o).getKeyID());
273    }
274    public int compareTo(Object o) { 
275        if ( ! (o instanceof Identity) ) return 1;
276        else return getKeyID().compareTo(((Identity)o).getKeyID());
277    }
278    public X509CertificateObject getCertificate() { return m_cert; }
279
280};
Note: See TracBrowser for help on using the repository browser.