|
RIPEMD160WithISO9796Part1AndRSASignatureImpl |
|
1 /* $RCSfile: RIPEMD160WithISO9796Part1AndRSASignatureImpl.java,v $ 2 * $Revision: 1.4 $ 3 * $Date: 2002/11/23 11:09:56 $ 4 * $Author: uwe_guenther $ 5 * $State: Exp $ 6 * 7 * Created on December 20, 2001 6:36 PM 8 * 9 * Copyright (C) 2001 Uwe Guenther <uwe@cscc.de> 10 * 11 * This file is part of the jhbci JCE-ServiceProvider. The jhbci JCE- 12 * ServiceProvider is a library, written in JavaTM, that should be 13 * used in HBCI banking applications (clients and may be servers), 14 * to do cryptographic operations. 15 * 16 * The jhbci library is free software; you can redistribute it and/or 17 * modify it under the terms of the GNU Lesser General Public 18 * License as published by the Free Software Foundation; either 19 * version 2.1 of the License, or (at your option) any later version. 20 * 21 * The jhbci library is distributed in the hope that it will be useful, 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 * Lesser General Public License for more details. 25 * 26 * You should have received a copy of the GNU Lesser General Public 27 * License along with this library; if not, write to the Free Software 28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 29 * 30 */ 31 32 package de.cscc.crypto.provider; 33 34 import java.security.AlgorithmParameters; 35 import java.security.InvalidAlgorithmParameterException; 36 import java.security.InvalidKeyException; 37 import java.security.PrivateKey; 38 import java.security.PublicKey; 39 import java.security.SecureRandom; 40 import java.security.SignatureException; 41 import java.security.interfaces.RSAKey; 42 import java.security.interfaces.RSAPrivateKey; 43 import java.security.interfaces.RSAPublicKey; 44 import java.security.spec.AlgorithmParameterSpec; 45 46 /** 47 * RIPEMD160WithISO9796Part1AndRSASignatureImpl Class. 48 * 49 * @author <a href=mailto:uwe@cscc.de>Uwe Günther</a> 50 * 51 * @version $Revision: 1.4 $ 52 */ 53 final class RIPEMD160WithISO9796Part1AndRSASignatureImpl implements Cloneable { 54 55 /** The RIPEMD160 message digest object. */ 56 private RIPEMD160MessageDigestImpl md = 57 new RIPEMD160MessageDigestImpl(); 58 59 /** The RIPEMD160 ISO9796-1:1991 codec object. */ 60 private ISO9796Part1RSACodec codec = new ISO9796Part1RSACodec(); 61 62 /** 63 * The length of the signature in bits according to the modulus of the 64 * RSA key. 65 */ 66 private int ks; 67 68 /** The object state variable. */ 69 private State state = State.UNINITIALIZED; 70 71 72 /** Creates new RIPEMD160WithISO9796Part1AndRSASignatureImpl. */ 73 public RIPEMD160WithISO9796Part1AndRSASignatureImpl() { 74 } 75 76 /** 77 * Creates and returns a copy of this object. 78 * 79 * @return a clone of this instance. 80 * @throws CloneNotSupportedException if the object's class does not 81 * support the <code>Cloneable</code> interface. Subclasses 82 * that override the <code>clone</code> method can also 83 * throw this exception to indicate that an instance cannot 84 * be cloned. 85 */ 86 public Object clone() throws CloneNotSupportedException { 87 RIPEMD160WithISO9796Part1AndRSASignatureImpl result = 88 (RIPEMD160WithISO9796Part1AndRSASignatureImpl) super.clone(); 89 result.md = (RIPEMD160MessageDigestImpl) this.md.clone(); 90 result.codec = (ISO9796Part1RSACodec) this.codec.clone(); 91 return result; 92 } 93 94 /** 95 * Indicates whether some other object is "equal to" this one. 96 * 97 * @param obj the reference object with which to compare. 98 * @return <code>true</code> if this object is the same as the obj 99 * argument; <code>false</code> otherwise. 100 * @see #hashCode() 101 * @see java.util.Hashtable 102 */ 103 public boolean equals(Object obj) { 104 //Only for performance. 105 if (this == obj) { 106 return true; 107 } 108 109 //If obj == null then instanceof returns false, see JLS 15.20.2 110 if (!(obj instanceof RIPEMD160WithISO9796Part1AndRSASignatureImpl)) { 111 return false; 112 } 113 114 RIPEMD160WithISO9796Part1AndRSASignatureImpl other = 115 (RIPEMD160WithISO9796Part1AndRSASignatureImpl)obj; 116 117 return this.md.equals(other.md) && 118 this.codec.equals(other.codec) && 119 this.ks == other.ks && 120 this.state == other.state; 121 } 122 123 /** 124 * Returns a hash code value for the object. 125 * 126 * @return a hash code value for this object. 127 * @see java.lang.Object#equals(java.lang.Object) 128 * @see java.util.Hashtable 129 */ 130 public int hashCode() { 131 int result = 17; 132 result = 37*result + this.md.hashCode(); 133 result = 37*result + this.codec.hashCode(); 134 result = 37*result + this.ks; 135 result = 37*result + this.state.hashCode(); 136 return result; 137 } 138 139 /** 140 * Returns a string representation of the object. 141 * 142 * @return a string representation of the object. 143 */ 144 public String toString() { 145 return "[RIPEMD160WithISO9796-1AndRSA - state: " + this.state + "]"; 146 } 147 148 /** 149 * Initializes this signature object with the specified 150 * private key for signing operations. 151 * 152 * @param privateKey the private key of the identity whose signature 153 * will be generated. 154 * 155 * @throws InvalidKeyException if the key is improperly encoded, parameters 156 * are missing, and so on. 157 */ 158 void initSign(PrivateKey privateKey) throws InvalidKeyException { 159 if (privateKey == null) { 160 throw new NullPointerException("Parameter privateKey is null."); 161 } 162 if (privateKey instanceof RSAPrivateKey) { 163 this.ks = ((RSAKey) privateKey).getModulus().bitLength() - 1; 164 } else { 165 throw new InvalidKeyException("Inappropriate Key."); 166 } 167 this.codec.initEncode(privateKey); 168 this.state = State.SIGN; 169 this.md.reset(); 170 } 171 172 /** 173 * Initializes this signature object with the specified 174 * private key and source of randomness for signing operations. 175 * 176 * <p>This concrete method has been added to this previously-defined 177 * abstract class. (For backwards compatibility, it cannot be abstract.) 178 * 179 * @param privateKey the private key of the identity whose signature 180 * will be generated. 181 * @param random the source of randomness 182 * 183 * @throws InvalidKeyException if the key is improperly encoded, parameters 184 * are missing, and so on. 185 */ 186 void initSign(PrivateKey privateKey, SecureRandom random) 187 throws InvalidKeyException { 188 initSign(privateKey); 189 } 190 191 /** 192 * Initializes this signature object with the specified 193 * public key for verification operations. 194 * 195 * @param publicKey the public key of the identity whose signature is 196 * going to be verified. 197 * 198 * @throws InvalidKeyException if the key is improperly 199 * encoded, parameters are missing, and so on. 200 */ 201 void initVerify(PublicKey publicKey) throws InvalidKeyException { 202 if (publicKey == null) { 203 throw new NullPointerException("Parameter publicKey is null."); 204 } 205 if (publicKey instanceof RSAPublicKey) { 206 this.ks = ((RSAKey) publicKey).getModulus().bitLength() - 1; 207 } else { 208 throw new InvalidKeyException("Inappropriate Key."); 209 } 210 this.codec.initDecode(publicKey); 211 this.state = State.VERIFY; 212 this.md.reset(); 213 } 214 215 /** 216 * Updates the data to be signed or verified 217 * using the specified byte. 218 * 219 * @param value the byte to use for the update. 220 * 221 * @throws SignatureException if the engine is not initialized 222 * properly. 223 */ 224 void update(byte value) throws SignatureException { 225 if (this.state == State.UNINITIALIZED) { 226 throw new SignatureException("Signature is not initialized."); 227 } 228 this.md.update(value); 229 } 230 231 /** 232 * Updates the data to be signed or verified, using the 233 * specified array of bytes, starting at the specified offset. 234 * 235 * @param values the array of bytes 236 * @param offset the offset to start from in the array of bytes 237 * @param len the number of bytes to use, starting at offset 238 * 239 * @throws SignatureException if the engine is not initialized 240 * properly 241 * @throws NullPointerException if outbuf is null. 242 * @throws IllegalArgumentException if offset or len is negative, or the 243 * sum of offset and len is greater than length of the values array. 244 */ 245 void update(byte[] values, int offset, int len) throws SignatureException { 246 if (this.state == State.UNINITIALIZED) { 247 throw new SignatureException("Signature is not initialized."); 248 } 249 if (values == null) { 250 throw new NullPointerException("Parameter values is null."); 251 } 252 if (offset < 0) { 253 throw new IllegalArgumentException("Parameter offset is less " + 254 "than zero."); 255 } 256 if (len < 0) { 257 throw new IllegalArgumentException("Parameter len is less " + 258 "than zero."); 259 } 260 if (offset + len > values.length) { 261 throw new IllegalArgumentException("Parameter offset + len is " + 262 "greater than outbuf.length ."); 263 } 264 this.md.update(values, offset, len); 265 } 266 267 /** 268 * Returns the signature bytes of all the data 269 * updated so far. 270 * The format of the signature depends on the underlying 271 * signature scheme. 272 * 273 * @return the signature bytes of the signing operation's result. 274 * 275 * @throws SignatureException if the engine is not initialized properly. 276 */ 277 byte[] sign() throws SignatureException { 278 if (this.state != State.SIGN) { 279 throw new SignatureException("Signature is not in SIGN state."); 280 } 281 282 try { 283 ISO9796Part1BitString messageDigest = 284 new ISO9796Part1BitString(this.md.digest(), 160); 285 286 ISO9796Part1BitString signature = 287 this.codec.encodeMessage(messageDigest, false); 288 289 /* 290 if (signature.getBitLength() == this.ks) { 291 return signature.getBitString(); 292 } else { 293 throw new SignatureException( 294 "Calculated Signature has a wrong length."); 295 } 296 */ 297 return signature.getBitString(); 298 299 } finally { 300 //If something goes wrong we should reset the md without fail! 301 //Also, if nothing goes wrong we should reset the md too. 302 this.md.reset(); 303 } 304 } 305 306 /** 307 * Finishes this signature operation and stores the resulting signature 308 * bytes in the provided buffer <code>outbuf</code>, starting at 309 * <code>offset</code>. 310 * The format of the signature depends on the underlying 311 * signature scheme. 312 * 313 * <p>The signature implementation is reset to its initial state 314 * (the state it was in after a call to one of the 315 * <code>engineInitSign</code> methods) 316 * and can be reused to generate further signatures with the same private 317 * key. 318 * 319 * This method should be abstract, but we leave it concrete for 320 * binary compatibility. Knowledgeable providers should override this 321 * method. 322 * 323 * @param outbuf buffer for the signature result. 324 * 325 * @param offset offset into <code>outbuf</code> where the signature is 326 * stored. 327 * 328 * @param len number of bytes within <code>outbuf</code> allotted for the 329 * signature. 330 * Both this default implementation and the SUN provider do not 331 * return partial digests. If the value of this parameter is less 332 * than the actual signature length, this method will throw a 333 * SignatureException. 334 * This parameter is ignored if its value is greater than or equal to 335 * the actual signature length. 336 * 337 * @return the number of bytes placed into <code>outbuf</code> 338 * 339 * @throws SignatureException if an error occurs or <code>len</code> 340 * is less than the actual signature length. 341 * @throws NullPointerException if outbuf is null. 342 * @throws IllegalArgumentException if offset or len is negative, or the 343 * sum of offset and len is greater than length of the outbuf array. 344 */ 345 int sign(byte[] outbuf, int offset, int len) throws SignatureException { 346 if (this.state != State.SIGN) { 347 throw new SignatureException("Signature is not in SIGN state."); 348 } 349 if (outbuf == null) { 350 throw new NullPointerException("Parameter outbuf is null."); 351 } 352 if (offset < 0) { 353 throw new IllegalArgumentException("Parameter offset is less " + 354 "than zero."); 355 } 356 if (len < 0) { 357 throw new IllegalArgumentException("Parameter len is less " + 358 "than zero."); 359 } 360 if (offset + len > outbuf.length) { 361 throw new IllegalArgumentException("Parameter offset + len is " + 362 "greater than outbuf.length ."); 363 } 364 if (((ks + 7) / 8) > len) { 365 throw new SignatureException("Existing space in outbuf is less " 366 + "than the signature length would be."); 367 } 368 369 //Calculate the Signature with sign() 370 byte[] result = sign(); 371 372 //Copy the Signature into the outbuf starting at offset. 373 System.arraycopy(result, 0, outbuf, offset, result.length); 374 375 //Return the number of bytes placed into outbuf. 376 return result.length; 377 } 378 379 /** 380 * Verifies the passed-in signature. 381 * 382 * @param sigBytes the signature bytes to be verified. 383 * 384 * @return true if the signature was verified, false if not. 385 * 386 * @throws SignatureException if the engine is not initialized 387 * properly, or the passed-in signature is improperly encoded or 388 * of the wrong type, etc. 389 */ 390 boolean verify(byte[] sigBytes) throws SignatureException { 391 if (this.state != State.VERIFY) { 392 throw new SignatureException("Signature is not in VERIFY state."); 393 } 394 if (sigBytes == null) { 395 throw new NullPointerException("Parameter signBytes is null."); 396 } 397 398 try { 399 ISO9796Part1BitString sigma = 400 new ISO9796Part1BitString (sigBytes, this.ks); 401 402 ISO9796Part1BitString recoveredMessageDigest = 403 this.codec.decodeSignature(sigma); 404 405 if (recoveredMessageDigest == null) { 406 return false; 407 408 } else { //(message != null) 409 ISO9796Part1BitString messageDigest = 410 new ISO9796Part1BitString(this.md.digest(), 160); 411 412 if (recoveredMessageDigest.equals(messageDigest)) { 413 return true; 414 } else { 415 return false; 416 } 417 } 418 } finally { 419 //If something goes wrong we should reset the md without fail! 420 //Also, if nothing goes wrong we should reset the md too. 421 this.md.reset(); 422 } 423 } 424 425 /** 426 * Verifies the passed-in signature in the specified array 427 * of bytes, starting at the specified offset. 428 * 429 * <p> Note: Subclasses should overwrite the default implementation. 430 * 431 * 432 * @param sigBytes the signature bytes to be verified. 433 * @param offset the offset to start from in the array of bytes. 434 * @param leng the number of bytes to use, starting at offset. 435 * 436 * @return true if the signature was verified, false if not. 437 * 438 * @throws SignatureException if the engine is not initialized 439 * properly, or the passed-in signature is improperly encoded or 440 * of the wrong type, etc. 441 */ 442 boolean verify(byte[] sigBytes, int offset, int len) 443 throws SignatureException { 444 if (this.state != State.VERIFY) { 445 throw new SignatureException("Signature is not in VERIFY state."); 446 } 447 if (sigBytes == null) { 448 throw new NullPointerException("Parameter signBytes is null."); 449 } 450 if (offset < 0) { 451 throw new IllegalArgumentException("Parameter offset is less " + 452 "than zero."); 453 } 454 if (len < 0) { 455 throw new IllegalArgumentException("Parameter len is less " + 456 "than zero."); 457 } 458 if (offset + len > sigBytes.length) { 459 throw new IllegalArgumentException("Parameter offset + len is " + 460 "greater than outbuf.length ."); 461 } 462 if (((ks + 7) / 8) != len) { 463 throw new SignatureException("Signature in sigBytes is not " + 464 ((ks + 7) / 8) + "bytes long."); 465 } 466 467 //Create a temporaly byte array that holds the 'sigBytes'. 468 byte[] tempSigBytes = new byte[len]; 469 470 //Copy the 'sigBytes' to 'tempSigBytes'. 471 System.arraycopy(sigBytes, offset, tempSigBytes, 0, len); 472 473 //Invoke the verify(byte[]) method with the 'tempSigBytesArray'. 474 return verify(tempSigBytes); 475 } 476 477 /** 478 * <p>This method is overridden by providers to initialize 479 * this signature engine with the specified parameter set. 480 * 481 * @param params the parameters 482 * 483 * @exception UnsupportedOperationException if this method is not 484 * overridden by a provider 485 * 486 * @throws InvalidAlgorithmParameterException if this method is 487 * overridden by a provider and the the given parameters 488 * are inappropriate for this signature engine 489 */ 490 void setParameter(AlgorithmParameterSpec params) 491 throws InvalidAlgorithmParameterException { 492 throw new UnsupportedOperationException("AlgorithmParameters are not " + 493 "supported for this signature."); 494 } 495 496 /** 497 * <p>This method is overridden by providers to return the 498 * parameters used with this signature engine, or null 499 * if this signature engine does not use any parameters. 500 * 501 * <p>The returned parameters may be the same that were used to initialize 502 * this signature engine, or may contain a combination of default and 503 * randomly generated parameter values used by the underlying signature 504 * implementation if this signature engine requires algorithm parameters 505 * but was not initialized with any. 506 * 507 * @return the parameters used with this signature engine, or null if this 508 * signature engine does not use any parameters 509 * 510 * @throws UnsupportedOperationException if this method is 511 * not overridden by a provider 512 */ 513 AlgorithmParameters getParameters() { 514 throw new UnsupportedOperationException("AlgorithmParameters are not " + 515 "supported for this signature."); 516 } 517 518 /** Type safe enum for the enclosing class object state. */ 519 private final static class State { 520 /** Name odf the state. */ 521 private final String name; 522 523 /** Constructor need only to called within this class. */ 524 private State(String name) { 525 this.name = name; 526 } 527 528 /** 529 * Returns a string representation of the object. 530 * 531 * @return a string representation of the object. 532 */ 533 public String toString() { 534 return this.name; 535 } 536 537 /** State constante if the enclosing class isn't initialized. */ 538 private static final State UNINITIALIZED = 539 new State("Uninitialized"); 540 541 /** State constante if the enclossing class is in Sign mode. */ 542 private static final State SIGN = new State("Sign"); 543 544 /** State constante if the enclossing class is in Verify mode. */ 545 private static final State VERIFY = new State("Verify"); 546 } 547 548 } 549
|
RIPEMD160WithISO9796Part1AndRSASignatureImpl |
|