1 package jsdsi;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.InputStream;
5 import java.security.InvalidKeyException;
6 import java.security.KeyPair;
7 import java.security.MessageDigest;
8 import java.security.NoSuchAlgorithmException;
9 import java.security.NoSuchProviderException;
10 import java.security.SignatureException;
11 import java.util.Iterator;
12
13 import jsdsi.sexp.Sexp;
14 import jsdsi.sexp.SexpList;
15 import jsdsi.sexp.SexpParseException;
16 import jsdsi.sexp.SexpUtil;
17 import jsdsi.util.DigestAlgoEnum;
18 import jsdsi.util.DigestUtils;
19 import jsdsi.util.KeyEnum;
20 import jsdsi.util.SignatureAlgoEnum;
21 import jsdsi.util.SignatureUtils;
22
23 /***
24 * A cryptographic signature.
25 *
26 * @author Sameer Ajmani
27 * @author Sean Radford
28 * @version $Revision: 1.8.2.1 $ $Date: 2005/11/08 03:12:52 $
29 */
30 public class Signature extends Obj implements Element {
31
32 private static final long serialVersionUID = -7728805907022170149L;
33
34 /***
35 * The principal that represents the signer.
36 */
37 private transient final Principal signer;
38
39 /***
40 * The hash of the signed data.
41 */
42 private transient final Hash signee;
43
44 /***
45 * The signature algorithm.
46 */
47 private transient final SignatureAlgoEnum algo;
48
49 /***
50 * The value of the signature.
51 */
52 private transient final byte[] data;
53
54 /***
55 * Creates a new Signature.
56 *
57 * @param i the signer
58 * @param h hash of the signed data
59 * @param a signature algorithm
60 * @param d signature value (<i>not</i> the data to sign)
61 *
62 */
63 public Signature(Principal i, Hash h, SignatureAlgoEnum a, byte[] d) {
64 assert(i != null) : "null signer";
65 assert(h != null) : "null signee";
66 assert(a != null) : "null algo";
67 assert(d != null) : "null data";
68 signer = i;
69 signee = h;
70 this.algo = a;
71 data = d;
72 }
73 /***
74 * Creates a new Signature.
75 *
76 * @param i the signer
77 * @param h hash of the signed data
78 * @param a signature algorithm
79 * @param d signature value (<i>not</i> the data to sign)
80 *
81 * @deprecated use {@link Signature(Principal, Hash, jsdsi.util.SignatureAlgoEnum, byte[]}
82 */
83 public Signature(Principal i, Hash h, String a, byte[] d) {
84 this(i, h, SignatureAlgoEnum.fromSpki(a), d);
85 }
86
87 /***
88 * Signs the given JSDSI Obj using the 'default' java.security.Provider.
89 * @param kp KeyPair containing the PrivateKey to sign with.
90 * @param o JSDSI Obj to sign.
91 * @param a hash algorythm to use.
92 * @return the signature.
93 * @throws JsdsiRuntimeException on error
94 */
95 public static Signature create(java.security.KeyPair kp,
96 Obj o, DigestAlgoEnum a) {
97 return create(kp, o.toByteArray(), a, null);
98 }
99
100 /***
101 * Signs the given byte array using the 'default' java.security.Provider.
102 * @param kp KeyPair containing the PrivateKey to sign with.
103 * @param bytes data to sign.
104 * @param a hash algorythm to use.
105 * @return the signature.
106 * @throws JsdsiRuntimeException on error
107 */
108 public static Signature create(java.security.KeyPair kp,
109 byte[] bytes, DigestAlgoEnum a) {
110 return create(kp, new ByteArrayInputStream(bytes), a, null);
111 }
112
113 /***
114 * Signs the given byte array using the 'default' java.security.Provider.
115 * @param kp KeyPair containing the PrivateKey to sign with.
116 * @param is data to sign.
117 * @param a hash algorythm to use.
118 * @return the signature.
119 * @throws JsdsiRuntimeException on error
120 */
121 public static Signature create(java.security.KeyPair kp,
122 InputStream is, DigestAlgoEnum a) {
123 return create(kp, is, a, null);
124 }
125
126 /***
127 * Signs the given JSDSI Obj using the specified java.security.Provider.
128 * @param kp KeyPair containing the PrivateKey to sign with.
129 * @param o JSDSI Obj to sign.
130 * @param a hash algorythm to use.
131 * @return the signature.
132 * @throws JsdsiRuntimeException on error
133 */
134 public static Signature create(java.security.KeyPair kp,
135 Obj o, DigestAlgoEnum a, String provider) {
136 return create(kp, o.toByteArray(), a, provider);
137 }
138
139 /***
140 * Signs the given byte array using the specified java.security.Provider.
141 * @param kp KeyPair containing the PrivateKey to sign with.
142 * @param bytes data to sign.
143 * @param a hash algorythm to use.
144 * @return the signature.
145 * @throws JsdsiRuntimeException on error
146 */
147 public static Signature create(java.security.KeyPair kp,
148 byte[] bytes,
149 DigestAlgoEnum a, String provider) {
150 return create(kp, new ByteArrayInputStream(bytes), a, provider);
151 }
152
153 /***
154 * Signs the given byte array using the specified java.security.Provider.
155 * @param kp KeyPair containing the PrivateKey to sign with.
156 * @param is data to sign.
157 * @param digestEnum hash algorythm to use.
158 * @return the signature.
159 * @throws JsdsiRuntimeException on error
160 */
161 public static Signature create(java.security.KeyPair kp,
162 InputStream is,
163 DigestAlgoEnum digestEnum,
164 String provider) {
165 assert(kp != null) : "null key pair";
166 assert(is != null) : "null data to sign";
167 assert(digestEnum != null) : "null hash algo";
168 assert(kp.getPublic() instanceof Principal) :
169 "public key must be a principal";
170 KeyEnum keyEnum = KeyEnum.fromJdk(kp.getPublic().getAlgorithm());
171 SignatureAlgoEnum sigEnum = SignatureAlgoEnum.create(digestEnum,
172 keyEnum );
173 java.security.Signature sig = SignatureUtils.getJdkSignature(
174 sigEnum.jdkName(),
175 provider);
176 try {
177 sig.initSign(kp.getPrivate());
178 } catch (InvalidKeyException e) {
179 throw new JsdsiRuntimeException("Error with signing PrivateKey",
180 e);
181 }
182 MessageDigest digester = DigestUtils.getDigest(digestEnum);
183 Iterator it = new jsdsi.util.InputStreamIterator(is);
184 while (it.hasNext()) {
185 byte[] bytes = (byte[]) it.next();
186 try {
187 sig.update(bytes);
188 } catch (SignatureException e) {
189 throw new JsdsiRuntimeException(
190 "Error updating signature engine with data to sign",
191 e);
192 }
193 digester.update(bytes);
194 }
195 byte[] d;
196 try {
197 d = sig.sign();
198 } catch (SignatureException e) {
199 throw new JsdsiRuntimeException("Error performing sign operation",
200 e);
201 }
202 return new Signature((Principal) kp.getPublic(),
203 new Hash(digestEnum, digester.digest(), null),
204 sigEnum,
205 d);
206 }
207
208
209
210
211 /***
212 * Signs the given JSDSI Obj using the 'default' java.security.Provider.
213 * @param kp the KeyPair containing the PrivateKey to sign with.
214 * @param o the JSDSI Obj to sign.
215 * @param a the name of the signing algorythm to use.
216 * @return the signature.
217 * @throws NoSuchAlgorithmException
218 * @throws InvalidKeyException
219 * @throws NoSuchProviderException
220 * @throws SignatureException
221 *
222 * @deprecated
223 */
224 public static Signature create(java.security.KeyPair kp,
225 Obj o,
226 String a)
227 throws NoSuchAlgorithmException,
228 InvalidKeyException,
229 NoSuchProviderException,
230 SignatureException {
231 return create(kp, o, a, null);
232 }
233
234 /***
235 * Signs the given JSDSI Obj.
236 * @param kp the KeyPair containing the PrivateKey to sign with.
237 * @param o the JSDSI Obj to sign.
238 * @param a the name of the signing algorythm to use.
239 * @param provider the name of the security Provider to use.
240 * @return the signature.
241 * @throws NoSuchAlgorithmException
242 * @throws InvalidKeyException
243 * @throws NoSuchProviderException
244 * @throws SignatureException
245 * @deprecated
246 */
247 public static Signature create(java.security.KeyPair kp,
248 Obj o,
249 String a,
250 String provider)
251 throws NoSuchAlgorithmException,
252 InvalidKeyException,
253 NoSuchProviderException,
254 SignatureException {
255 return create(kp, o.toByteArray(), a, provider);
256 }
257
258 /***
259 * Signs some data given as a <code>byte[]</code> using the
260 * 'default' java.security.Provider.
261 * @param kp the KeyPair containing the PrivateKey to sign with.
262 * @param b the data to sign.
263 * @param a the name of the signing algorythm to use.
264 * @return the signature.
265 * @throws NoSuchAlgorithmException
266 * @throws InvalidKeyException
267 * @throws NoSuchProviderException
268 * @throws SignatureException
269 * @deprecated
270 */
271 public static Signature create(java.security.KeyPair kp,
272 byte[] b,
273 String a)
274 throws NoSuchAlgorithmException,
275 InvalidKeyException,
276 NoSuchProviderException,
277 SignatureException {
278 return create(kp, b, a, null);
279 }
280
281 /***
282 * Signs some data given as a <code>byte[]</code>.
283 * @param kp the KeyPair containing the PrivateKey to sign with.
284 * @param b the data to sign.
285 * @param a the name of the signing algorythm to use.
286 * @param provider the name of the security Provider to use.
287 * @return the signature.
288 * @throws NoSuchAlgorithmException
289 * @throws InvalidKeyException
290 * @throws NoSuchProviderException
291 * @throws SignatureException
292 * @deprecated
293 */
294 public static Signature create(java.security.KeyPair kp,
295 byte[] b,
296 String a,
297 String provider)
298 throws NoSuchAlgorithmException,
299 InvalidKeyException,
300 NoSuchProviderException,
301 SignatureException {
302 return create(kp, new ByteArrayInputStream(b), a, provider);
303 }
304
305 /***
306 * Signs some data given as an <code>java.io.InputStream</code>
307 * using the 'default' java.security.Provider.
308 * @param kp the KeyPair containing the PrivateKey to sign with.
309 * @param toSign the InputStream with the data to sign.
310 * @param a the name of the signing algorythm to use.
311 * @return the signature.
312 * @throws NoSuchAlgorithmException
313 * @throws InvalidKeyException
314 * @throws NoSuchProviderException
315 * @throws SignatureException
316 * @deprecated
317 */
318 public static Signature create(java.security.KeyPair kp,
319 InputStream toSign,
320 String a)
321 throws InvalidKeyException,
322 NoSuchAlgorithmException,
323 NoSuchProviderException,
324 SignatureException {
325 return create(kp, toSign, a, null);
326 }
327
328 /***
329 * Signs some data given as a <code>java.io.InputStream</code>.
330 * @param kp the KeyPair containing the PrivateKey to sign with.
331 * @param toSign the InputStream with the data to sign.
332 * @param a the name of the signing algorythm to use
333 * @param provider the name of the security Provider to use.
334 * @return the signature.
335 * @throws NoSuchAlgorithmException
336 * @throws InvalidKeyException
337 * @throws NoSuchProviderException
338 * @throws SignatureException
339 * @deprecated
340 */
341 public static Signature create(java.security.KeyPair kp,
342 InputStream toSign,
343 String a,
344 String provider)
345 throws NoSuchAlgorithmException,
346 NoSuchProviderException,
347 InvalidKeyException,
348 SignatureException {
349 SignatureAlgoEnum sigEnum = SignatureAlgoEnum.fromJdk(a);
350 DigestAlgoEnum digestEnum = sigEnum.getDigestEnum();
351 return create(kp, toSign, digestEnum, provider);
352 }
353
354 /***
355 * Using the default security Provider, verifies that the
356 * corresponding PrivateKey for <code>key</code> generated
357 * <code>this</code> Signature for <code>o</code>
358 * @param key the PublicKey
359 * @param o the jsdsi object that was (alledgedly) signed
360 * @return <code>true</code> if the signature verifies
361 * @throws JsdsiRuntimeException on error
362 */
363 public boolean verify(java.security.PublicKey key,
364 Obj o)
365 throws InvalidKeyException,
366 NoSuchAlgorithmException,
367 NoSuchProviderException,
368 SignatureException {
369 return verify(key, o, null);
370 }
371
372 public boolean verify(java.security.PublicKey key,
373 Obj o,
374 String provider)
375 throws InvalidKeyException,
376 NoSuchAlgorithmException,
377 NoSuchProviderException,
378 SignatureException {
379 return verify(key, o.toByteArray(), provider);
380 }
381
382 public boolean verify(java.security.PublicKey key,
383 byte[] b)
384 throws InvalidKeyException,
385 NoSuchAlgorithmException,
386 NoSuchProviderException,
387 SignatureException {
388 return verify(key, b, null);
389 }
390
391 public boolean verify(java.security.PublicKey key,
392 byte[] b,
393 String provider)
394 throws InvalidKeyException,
395 NoSuchAlgorithmException,
396 NoSuchProviderException,
397 SignatureException {
398 return verify(key, new ByteArrayInputStream(b), provider);
399 }
400
401 public boolean verify(java.security.PublicKey key,
402 InputStream toCheck) throws InvalidKeyException,
403 NoSuchAlgorithmException, NoSuchProviderException, SignatureException {
404 return verify(key, toCheck, null);
405 }
406
407 /***
408 * Using the <code>provider</code>, verifies that the corresponding
409 * PrivateKey for <code>key</code> generated <code>this</code>
410 * Signature for the data given by <code>toCheck</code>
411 * @param key the PublicKey
412 * @param toCheck an InputStream of data
413 * @return <code>true</code> if the signature verifies
414 * @throws JsdsiRuntimeException on error
415 */
416 public boolean verify(java.security.PublicKey key,
417 InputStream toCheck,
418 String provider)
419 throws NoSuchAlgorithmException,
420 NoSuchProviderException,
421 InvalidKeyException,
422 SignatureException {
423 String algo = this.algo.jdkName();
424 java.security.Signature sig =
425 (provider == null)
426 ? java.security.Signature.getInstance(algo)
427 : java.security.Signature.getInstance(algo, provider);
428 sig.initVerify(key);
429
430 Iterator it = new jsdsi.util.InputStreamIterator(toCheck);
431 while (it.hasNext()) {
432 byte[] bytes = (byte[]) it.next();
433 sig.update(bytes);
434 }
435 return sig.verify(data);
436 }
437
438 /***
439 * @return the principal representing the signer.
440 */
441 public Principal getSigner() {
442 return signer;
443 }
444
445 /***
446 * @return the hash of the signed data.
447 */
448 public Hash getSignee() {
449 return signee;
450 }
451
452 /***
453 * @return the JDK name for the signature algorithm.
454 */
455 public String getAlgorithm() {
456 return this.algo.jdkName();
457 }
458
459 /***
460 * @return the signature algorythm
461 */
462 public SignatureAlgoEnum getSignatureEnum() {
463 return this.algo;
464 }
465
466 /***
467 * @return the value of the signature.
468 */
469 public byte[] getData() {
470 return data;
471 }
472
473 public boolean equals(Object o) {
474 if (o instanceof Signature) {
475 Signature s = (Signature) o;
476 return signer.equals(s.signer)
477 && signee.equals(s.signee)
478 && algo.equals(s.algo)
479 && Util.equals(data, s.data);
480 }
481 return false;
482 }
483
484 public int hashCode() {
485 return signer.hashCode()
486 ^ signee.hashCode()
487 ^ algo.hashCode()
488 ^ Util.hashCode(data);
489 }
490
491 public SexpList toSexp() {
492 Sexp[] ss = new Sexp[3];
493 ss[0] = getSignee().toSexp();
494 ss[1] = getSigner().toSexp();
495 Sexp[] sig = new Sexp[1];
496 sig[0] = SexpUtil.toSexp(getData());
497 ss[2] = SexpUtil.toSexp(this.algo.spkiName(), sig);
498 return SexpUtil.toSexp("signature", ss);
499 }
500
501 static Signature parseSignature(SexpList l) throws SexpParseException {
502 Iterator sbody = SexpUtil.getBody(l);
503 // (signature <hash> <principal> (<algo> <data))
504 Hash signee = Hash.parseHash(SexpUtil.getNextList(sbody, "sig hash"));
505 Principal signer = Principal.parsePrincipal(
506 SexpUtil.getNextList(sbody, "sig principal"));
507 SexpList algoblock = SexpUtil.getNextList(sbody, "sig algo block");
508 SexpUtil.checkDone(sbody, "signature");
509 String algo = algoblock.getType();
510 Iterator algobody = SexpUtil.getBody(algoblock);
511 byte[] data = SexpUtil.getNextByteArray(algobody, "sig data");
512 SexpUtil.checkDone(algobody, "signature");
513 SignatureAlgoEnum sigEnum = calculateSignatureEnum(algo);
514 return new Signature(signer, signee, sigEnum, data);
515 }
516
517 /***
518 * Temporary method to cope with legacy certificates/signatures
519 * which incorrectly have JDK algorithm names in their SExpression.
520 * @param algo
521 * @return
522 * @todo Method should be removed in the future when legacy data is
523 * no longer an issue
524 */
525 static SignatureAlgoEnum calculateSignatureEnum(String algo) {
526 try {
527 return SignatureAlgoEnum.fromSpki(algo);
528 } catch (JsdsiRuntimeException e) {
529 return SignatureAlgoEnum.fromJdk(algo);
530 }
531 }
532
533 public static void main(String[] args) throws Exception
534 {
535 KeyPair kp = jsdsi.util.KeyPairFactory.create(KeyEnum.RSA);
536
537 jsdsi.Signature sig1 = jsdsi.Signature.create
538 (kp, new jsdsi.StringTag("member"),"MD5withRSA");
539 jsdsi.Signature sig2 = jsdsi.Signature.create
540 (kp, new jsdsi.StringTag("member"),"MD5withRSA");
541
542 System.out.println(sig1.equals(sig2));
543 System.out.println(sig1 == sig2);
544
545 System.out.println("sig.hashCode()");
546 System.out.println(sig1.hashCode());
547 System.out.println(sig2.hashCode());
548
549 System.out.println("sig.getSigner().hashCode()");
550 System.out.println(sig1.getSigner().hashCode());
551 System.out.println(sig2.getSigner().hashCode());
552
553 System.out.println("sig.getSignee().hashCode()");
554 System.out.println(sig1.getSignee().hashCode());
555 System.out.println(sig2.getSignee().hashCode());
556
557 System.out.println("sig.getAlgorithm().hashCode()");
558 System.out.println(sig1.getAlgorithm().hashCode());
559 System.out.println(sig2.getAlgorithm().hashCode());
560
561 System.out.println("Util.hashCode(sig.getData())");
562 System.out.println(Util.hashCode(sig1.getData()));
563 System.out.println(Util.hashCode(sig2.getData()));
564
565 System.out.println("sig.getData().hashCode()");
566 System.out.println(sig1.getData().hashCode());
567 System.out.println(sig2.getData().hashCode());
568 }
569 }
This page was automatically generated by Maven