Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: jsdsi/Certificate.java


1   /*
2    * Copyright 2002 Massachusetts Institute of Technology
3    *   
4    * Permission to use, copy, modify, and distribute this program for any
5    * purpose and without fee is hereby granted, provided that this
6    * copyright and permission notice appear on all copies and supporting
7    * documentation, the name of M.I.T. not be used in advertising or
8    * publicity pertaining to distribution of the program without specific
9    * prior permission, and notice be given in supporting documentation that
10   * copying and distribution is by permission of M.I.T.  M.I.T. makes no
11   * representations about the suitability of this software for any
12   * purpose.  It is provided "as is" without express or implied warranty.
13   */
14  package jsdsi;
15  
16  import java.security.MessageDigest;
17  import java.security.PublicKey;
18  import java.security.NoSuchAlgorithmException;
19  import java.security.NoSuchProviderException;
20  import java.security.InvalidKeyException;
21  import java.security.SignatureException;
22  import java.security.cert.CertificateException;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Arrays;
26  import java.util.ArrayList;
27  
28  /**
29   * A Cert along with its validators (verification path, signature, and
30   * online test results).  Whereas a Cert is simply an unauthenticated
31   * statement, a Certificate is self-validating and thus can be
32   * considered authentic if verify() succeeds.  A Certificate is
33   * serialized as a SPKI/SDSI Sequence.
34   * 
35   * @see Cert
36   * @see Signature
37   * @see Sequence
38   * 
39   * @author Sameer Ajmani
40   * @version $Revision: 1.2 $ $Date: 2003/04/22 21:37:44 $
41   */
42  public class Certificate extends java.security.cert.Certificate {
43    /**
44     * Issuer of this <code>Certificate</code>.
45     */
46    private PublicKey issuer; // if null, cert.getIssuer() is a key
47  
48    /**
49     * <code>Cert</code> of this certificate.
50     */
51    private Cert cert;
52  
53    // TODO: VerificationPath ...
54  
55    /**
56     * <code>Signature</code> of this <code>Certificate</code>.
57     */
58    private Signature sig;
59  
60    // TODO: OnlineTestResult[] ...
61  
62    /**
63     * Creates a new <code>Certificate</code> from a given public key, 
64     * <code>Cert</code>, and signature.
65     * 
66     * @param  k public key of the issuer (principal).
67     * @param  c <code>Cert</code> of this <code>Certificate</code>.
68     * @param  s <code>Signature</code> of this <code>Certificate</code>.
69     * @throws CertificateException if <code>k</code> is <code>null</code> or
70     *         not a <code>PublicKey</code>.
71     */
72    public Certificate(PublicKey k, Cert c, Signature s)
73      throws CertificateException {
74      super("SPKI");
75      assert(c != null) : "null cert";
76      assert(s != null) : "null signature";
77      issuer = k;
78      cert = c;
79      sig = s;
80      if ((issuer == null) && !(c.getIssuer() instanceof PublicKey)) {
81        throw new CertificateException("issuer must be a PublicKey");
82      }
83    }
84  
85    /**
86     * Creates a new <code>Certificate</code> from a given <code>Cert</code>
87     * and <code>Signature</code>.
88     * 
89     * @param  c <code>Cert</code> to create a new <code>Certificate</code> 
90     *         from.
91     * @param  s <code>Signature</code> to create a new 
92     *         <code>Certificate</code> from.
93     * @throws CertificateException
94     */
95    public Certificate(Cert c, Signature s) throws CertificateException {
96      this(null, c, s);
97    }
98  
99    /**
100    * @see java.security.cert.Certificate#getPublicKey()
101    */
102   public java.security.PublicKey getPublicKey() {
103     if (issuer == null) {
104       return (PublicKey) cert.getIssuer();
105     } else {
106       return issuer;
107     }
108   }
109 
110   /**
111    * @see java.security.cert.Certificate#verify(PublicKey)
112    */
113   public void verify(java.security.PublicKey key)
114     throws
115       CertificateException,
116       NoSuchAlgorithmException,
117       InvalidKeyException,
118       NoSuchProviderException,
119       SignatureException {
120     verify(key, null);
121   }
122 
123   /**
124    * @see java.security.cert.Certificate#verify(PublicKey, String)
125    */
126   public void verify(java.security.PublicKey key, String sigProvider)
127     throws
128       CertificateException,
129       NoSuchAlgorithmException,
130       InvalidKeyException,
131       NoSuchProviderException,
132       SignatureException {
133     assert(key != null) : "null key";
134     if (!cert.getIssuer().samePrincipalAs(sig.getSigner())) {
135       throw new CertificateException("issuer does not match signer");
136     }
137     if (!(key instanceof Principal)
138       || !cert.getIssuer().samePrincipalAs((Principal) key)) {
139       throw new CertificateException("verification key does not match issuer");
140     }
141     if (!sig.verify(key, cert, sigProvider)) {
142       throw new SignatureException("signature verification failed");
143     }
144     // TODO: check verification path, online test results, etc.
145   }
146 
147   /**
148    * Returns the <code>Cert</code> of this <code>Certificate</code>.
149    * 
150    * @return the <code>Cert</code> of this <code>Certificate</code>.
151    */
152   public Cert getCert() {
153     return cert;
154   }
155 
156   /**
157    * Checks if a given <code>Iterator</code> has more elements.
158    * 
159    * @param  elems <code>Iterator</code> to check for if it has more
160    *         elements.
161    * @throws CertificateException if <code>elems</code> does not have
162    *         any more elements.
163    */
164   private static void check(Iterator elems) throws CertificateException {
165     if (!elems.hasNext()) {
166       throw new CertificateException("Not enough elements in sequence");
167     }
168   }
169 
170   /**
171    * Factory method for creating a new <code>Certificate</code> from an 
172    * iterator that holds a <code>Cert</code> and a <code>Signature</code>.
173    * 
174    * @param  elems <code>Iterator</code> holding a <code>Cert</code> and a
175    *         <code>Signature</code> (in this order).
176    * @return the certificate created from the <code>Cert</code> and the
177    *         <code>Signature</code> in <code>elems</code>.
178    * @throws CertificateException if <code>elems</code> does not contain
179    *         the expected values.
180    */
181   public static Certificate fromElements(Iterator elems)
182     throws CertificateException {
183     PublicKey issuer = null;
184     check(elems);
185     Element e = (Element) elems.next();
186     if (e instanceof PublicKey) {
187       issuer = (PublicKey) e;
188       check(elems);
189       e = (Element) elems.next();
190     }
191     if (!(e instanceof Cert)) {
192       throw new CertificateException("Expected cert");
193     }
194     Cert cert = (Cert) e;
195     check(elems);
196     e = (Element) elems.next();
197     if (!(e instanceof Signature)) {
198       throw new CertificateException("Expected signature");
199     }
200     Signature sig = (Signature) e;
201     // TODO: include verification path, online test results, etc.
202     return new Certificate(issuer, cert, sig);
203   }
204 
205   /**
206    * Adds the issuer (if not <code>null</code>), the <code>Cert</code>,
207    * and the <code>Signture</code> of this <code>Certificate</code> to
208    * the given List.
209    * 
210    * @param  elems <code>List</code> to add the issuer (if not 
211    *         <code>null</code>), the <code>Cert</code>, and the 
212    *         <code>Signture</code> of this <code>Certificate</code> to.
213    */
214   public void toElements(List elems) {
215     if (issuer != null) {
216       elems.add(issuer);
217       // TODO: if key is hashed in cert or sig, include hash ops
218     }
219     elems.add(cert);
220     elems.add(sig);
221     // TODO: include verification path, online test results, etc.
222   }
223 
224   /**
225    * Factory method that creates a new <code>Certificate</code> from a given
226    * <code>Sequence</code> that contains a <code>Cert</code> and a
227    * <code>Signature</code> (in this order).
228    * 
229    * @param  seq <code>Sequence</code> holding the <code>Cert</code> and the
230    *         <code>Signature</code> to create the <code>Certificate</code> 
231    *         from.
232    * @return the new <code>Certificate</code>.
233    * @throws CertificateException if the creation of the 
234    *         <code>Certificate</code> failed.
235    */
236   public static Certificate fromSequence(Sequence seq)
237     throws CertificateException {
238     return fromElements(Arrays.asList(seq.getElements()).iterator());
239   }
240 
241   /**
242    * Returns a <code>Sequence</code> containing the issuer (if not 
243    * <code>null</code>), the <code>Cert</code>, and the
244    * <code>Signature</code> of this <code>Certificate</code>.
245    * @return Sequence
246    */
247   public Sequence toSequence() {
248     ArrayList elems = new ArrayList();
249     toElements(elems);
250     return new Sequence((Element[]) elems.toArray(new Element[0]));
251   }
252 
253   /**
254    * @see java.lang.Object#toString()
255    */
256   public String toString() {
257     return toSequence().toString();
258   }
259 
260   /**
261    * @see java.security.cert.Certificate#getEncoded()
262    */
263   public byte[] getEncoded() {
264     return toSequence().toByteArray();
265   }
266 
267   /**
268    * Returns the format of this <code>Certificate</code>, namely
269    * <code>&quot;SEXP&quot;</code>.
270    * 
271    * @return the format of this <code>Certificate</code>
272    *         (<code>&quot;SEXP&quot;</code>).
273    */
274   public String getFormat() {
275     return "SEXP";
276   }
277 }