View Javadoc
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