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