source: java/net/deterlab/abac/Identity.java @ 84f0e7a

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

Initial run at unifying the interface.

  • Property mode set to 100644
File size: 7.9 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;
17// import org.bouncycastle.jce.provider.X509CertificateObject;
18import org.bouncycastle.openssl.PEMReader;
19import org.bouncycastle.openssl.PEMWriter;
20
21public class Identity implements Comparable {
22    private X509Certificate 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 X509Certificate) {
40                if ( m_cn == null ) 
41                    init((X509Certificate)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(X509Certificate c) throws
59        CertificateException, NoSuchAlgorithmException,InvalidKeyException,
60        NoSuchProviderException, SignatureException, IOException {
61            m_cert = (X509Certificate) 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        X509Certificate a = (X509Certificate) gen.generate(kp.getPrivate());
88        init(a);
89    }
90
91
92
93    /**
94     * Construct from a file, containing a self-signed PEM certificate.
95     */
96    public Identity(File file) throws 
97        CertificateException, NoSuchAlgorithmException,InvalidKeyException,
98        NoSuchProviderException, SignatureException, FileNotFoundException,
99        IOException { 
100            kp = null;
101            init(new FileReader(file));
102        }
103
104    /**
105     * Construct from a reader, containing a self-signed PEM certificate.
106     */
107    public Identity(Reader r) throws 
108        CertificateException, NoSuchAlgorithmException,InvalidKeyException,
109        NoSuchProviderException, SignatureException, IOException {
110            kp = null;
111            init(r);
112        }
113
114    /**
115     * Construct from an InputStream, containing a self-signed PEM certificate.
116     */
117    public Identity(InputStream s) throws 
118        CertificateException, NoSuchAlgorithmException,InvalidKeyException,
119        NoSuchProviderException, SignatureException, IOException { 
120            kp = null;
121            init(new InputStreamReader(s));
122        }
123
124    /**
125     * Construct from an X509Certificate, if you parsed one somewhere
126     * else.
127     */
128    public Identity(X509Certificate cert) throws 
129        CertificateException, NoSuchAlgorithmException,InvalidKeyException,
130        NoSuchProviderException, SignatureException, FileNotFoundException,
131        IOException { 
132            kp = null;
133            init(cert);
134        }
135
136    /**
137     * Write the PEM key to the given writer.
138     */
139    public boolean writePrivateKey(Writer w) throws IOException {
140        if (kp != null ) {
141            PEMWriter pw = new PEMWriter(w);
142
143            pw.writeObject(kp.getPrivate());
144            pw.flush();
145            return true;
146        }
147        else return false;
148    }
149
150    /**
151     * Write the PEM key to a file with the given name.
152     */
153    public boolean writePrivateKey(String fn) 
154            throws IOException, FileNotFoundException {
155        return writePrivateKey(new FileWriter(fn));
156    }
157
158    /**
159     * Write the PEM key to the given file.
160     */
161    public boolean writePrivateKey(File fn) 
162            throws IOException, FileNotFoundException {
163        return writePrivateKey(new FileWriter(fn));
164    }
165
166    /**
167     * Write the PEM key to the given OutputStream.
168     */
169    public boolean writePrivateKey(OutputStream s) 
170            throws IOException, FileNotFoundException {
171        return writePrivateKey(new OutputStreamWriter(s));
172    }
173
174
175    /**
176     * Write the PEM cert to the given writer.
177     */
178    public void write(Writer w) throws IOException {
179        PEMWriter pw = new PEMWriter(w);
180
181        pw.writeObject(m_cert);
182        pw.flush();
183    }
184
185    /**
186     * Write the PEM cert to a file with the given name.
187     */
188    public void write(String fn) throws IOException, FileNotFoundException {
189        write(new FileWriter(fn));
190    }
191
192    /**
193     * Write the PEM cert to the given file.
194     */
195    public void write(File fn) throws IOException, FileNotFoundException {
196        write(new FileWriter(fn));
197    }
198
199    /**
200     * Write the PEM cert to the given OutputStream.
201     */
202    public void write(OutputStream s) 
203        throws IOException, FileNotFoundException {
204        write(new OutputStreamWriter(s));
205    }
206
207
208    /**
209     * Get to the SHA1 hash of the key.
210     */
211    public static String extractKeyID(PublicKey k) {
212        SubjectPublicKeyInfo ki = extractSubjectPublicKeyInfo(k);
213        SubjectKeyIdentifier id = 
214            SubjectKeyIdentifier.createSHA1KeyIdentifier(ki);
215
216        // Now format it into a string for keeps
217        Formatter fmt = new Formatter(new StringWriter());
218        for (byte b: id.getKeyIdentifier())
219            fmt.format("%02x", b);
220        return fmt.out().toString();
221    }
222
223    /**
224     * Extratct the SubjectPublicKeyInfo.  Useful for some other encryptions,
225     * notably Certificate.make_cert().
226     */
227    public static SubjectPublicKeyInfo extractSubjectPublicKeyInfo(PublicKey k) {
228        ASN1Sequence seq = null;
229        try {
230            seq = (ASN1Sequence) new ASN1InputStream(
231                    k.getEncoded()).readObject();
232        }
233        catch (IOException ie) {
234            // Badly formatted key??
235            return null;
236        }
237        return new SubjectPublicKeyInfo(seq);
238    }
239
240
241    // Accessors
242    public String getKeyID() { return m_keyid; }
243    public String getName() { return m_cn; }
244    public String toString() { 
245        String s = m_keyid + " (" + m_cn ;
246
247        if (m_keyid != null ) s += " [keyed]";
248        s += ")";
249        return s;
250    }
251    /**
252     * Associate a keypair with this Identity.  If the ID has a certificate,
253     * make sure that the keypair matches it.  If not throw an
254     * IllegalArgumentException.
255     */
256    public void setKeyPair(KeyPair k) {
257        if (m_keyid != null) {
258            String kid = extractKeyID(k.getPublic());
259
260            if ( kid != null && kid.equals(m_keyid)) kp = k;
261            else 
262                throw new IllegalArgumentException(
263                        "Keypair does not match certificate");
264        }
265        else kp = k;
266    }
267    public KeyPair getKeyPair() { return kp; }
268    public boolean equals(Object o) { 
269        if ( o == null ) return false;
270        else if ( ! (o instanceof Identity) ) return false;
271        else return getKeyID().equals(((Identity)o).getKeyID());
272    }
273    public int compareTo(Object o) { 
274        if ( ! (o instanceof Identity) ) return 1;
275        else return getKeyID().compareTo(((Identity)o).getKeyID());
276    }
277    public X509Certificate getCertificate() { return m_cert; }
278
279};
Note: See TracBrowser for help on using the repository browser.