source: java/net/deterlab/abac/Identity.java @ 8a93b41

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

Save private keys as well.

  • Property mode set to 100644
File size: 7.8 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     * Get to the SHA1 hash of the key.
210     */
211    public static String extractKeyID(PublicKey k) {
212        ASN1Sequence seq = null;
213        try {
214            seq = (ASN1Sequence) new ASN1InputStream(
215                    k.getEncoded()).readObject();
216        }
217        catch (IOException ie) {
218            // Badly formatted key??
219            return null;
220        }
221        SubjectPublicKeyInfo ki = new SubjectPublicKeyInfo(seq);
222        SubjectKeyIdentifier id = 
223            SubjectKeyIdentifier.createSHA1KeyIdentifier(ki);
224
225        // Now format it into a string for keeps
226        Formatter fmt = new Formatter(new StringWriter());
227        for (byte b: id.getKeyIdentifier())
228            fmt.format("%02x", b);
229        return fmt.out().toString();
230    }
231
232    // Accessors
233    public String getKeyID() { return m_keyid; }
234    public String getName() { return m_cn; }
235    public String toString() { 
236        String s = m_keyid + " (" + m_cn ;
237
238        if (m_keyid != null ) s += " [keyed]";
239        s += ")";
240        return s;
241    }
242    /**
243     * Associate a keypair with this Identity.  If the ID has a certificate,
244     * make sure that the keypair matches it.  If not throw an
245     * IllegalArgumentException.
246     */
247    public void setKeyPair(KeyPair k) {
248        if (m_keyid != null) {
249            String kid = extractKeyID(k.getPublic());
250
251            if ( kid != null && kid.equals(m_keyid)) kp = k;
252            else 
253                throw new IllegalArgumentException(
254                        "Keypair does not match certificate");
255        }
256        else kp = k;
257    }
258    public KeyPair getKeyPair() { return kp; }
259    public boolean equals(Object o) { 
260        if ( o == null ) return false;
261        else if ( ! (o instanceof Identity) ) return false;
262        else return getKeyID().equals(((Identity)o).getKeyID());
263    }
264    public int compareTo(Object o) { 
265        if ( ! (o instanceof Identity) ) return 1;
266        else return getKeyID().compareTo(((Identity)o).getKeyID());
267    }
268    public X509CertificateObject getCertificate() { return m_cert; }
269
270};
Note: See TracBrowser for help on using the repository browser.