|
ISO9796Part1WithRSASignatureImpl |
|
1 /* $RCSfile: ISO9796Part1WithRSASignatureImpl.java,v $ 2 * $Revision: 1.3 $ 3 * $Date: 2002/11/23 11:09:56 $ 4 * $Author: uwe_guenther $ 5 * $State: Exp $ 6 * 7 * Created on October 20, 2002 3:27 PM 8 * 9 * Copyright (C) 2002 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 * ISO9796Part1WithRSASignatureImpl Class. 48 * 49 * @author <a href=mailto:uwe@cscc.de>Uwe Günther</a> 50 * 51 * @version $Revision: 1.3 $ 52 */ 53 final class ISO9796Part1WithRSASignatureImpl implements Cloneable { 54 55 /** The ISO9796Part1WithRSASignatureByteBuffer message buffer object. */ 56 private ISO9796Part1WithRSASignatureByteBuffer mb = 57 new ISO9796Part1WithRSASignatureByteBuffer(); 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 ISO9796Part1WithRSASignatureImpl. */ 73 public ISO9796Part1WithRSASignatureImpl() { 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 ISO9796Part1WithRSASignatureImpl result = 88 (ISO9796Part1WithRSASignatureImpl) super.clone(); 89 result.mb = (ISO9796Part1WithRSASignatureByteBuffer) this.mb.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 ISO9796Part1WithRSASignatureImpl)) { 111 return false; 112 } 113 114 ISO9796Part1WithRSASignatureImpl other = 115 (ISO9796Part1WithRSASignatureImpl)obj; 116 117 return this.mb.equals(other.mb) && 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.mb.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 "[ISO9796-1WithRSASignatureImpl - 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.mb.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.mb.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.mb.add(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.mb.add(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 if (this.mb.isEmpty()) { 282 throw new SignatureException("You have to add at least one byte " + 283 "to sign a message."); 284 } 285 286 try { 287 288 ISO9796Part1BitString signature = 289 this.codec.encodeMessage(this.mb.fetch(), false); 290 291 return signature.getBitString(); 292 293 } finally { 294 //If something goes wrong we should reset the mb without fail! 295 //Also, if nothing goes wrong we should reset the mb too. 296 this.mb.reset(); 297 } 298 } 299 300 /** 301 * Finishes this signature operation and stores the resulting signature 302 * bytes in the provided buffer <code>outbuf</code>, starting at 303 * <code>offset</code>. 304 * The format of the signature depends on the underlying 305 * signature scheme. 306 * 307 * <p>The signature implementation is reset to its initial state 308 * (the state it was in after a call to one of the 309 * <code>engineInitSign</code> methods) 310 * and can be reused to generate further signatures with the same private 311 * key. 312 * 313 * This method should be abstract, but we leave it concrete for 314 * binary compatibility. Knowledgeable providers should override this 315 * method. 316 * 317 * @param outbuf buffer for the signature result. 318 * 319 * @param offset offset into <code>outbuf</code> where the signature is 320 * stored. 321 * 322 * @param len number of bytes within <code>outbuf</code> allotted for the 323 * signature. 324 * Both this default implementation and the SUN provider do not 325 * return partial digests. If the value of this parameter is less 326 * than the actual signature length, this method will throw a 327 * SignatureException. 328 * This parameter is ignored if its value is greater than or equal to 329 * the actual signature length. 330 * 331 * @return the number of bytes placed into <code>outbuf</code> 332 * 333 * @throws SignatureException if an error occurs or <code>len</code> 334 * is less than the actual signature length. 335 * @throws NullPointerException if outbuf is null. 336 * @throws IllegalArgumentException if offset or len is negative, or the 337 * sum of offset and len is greater than length of the outbuf array. 338 */ 339 int sign(byte[] outbuf, int offset, int len) throws SignatureException { 340 if (this.state != State.SIGN) { 341 throw new SignatureException("Signature is not in SIGN state."); 342 } 343 if (outbuf == null) { 344 throw new NullPointerException("Parameter outbuf is null."); 345 } 346 if (offset < 0) { 347 throw new IllegalArgumentException("Parameter offset is less " + 348 "than zero."); 349 } 350 if (len < 0) { 351 throw new IllegalArgumentException("Parameter len is less " + 352 "than zero."); 353 } 354 if (offset + len > outbuf.length) { 355 throw new IllegalArgumentException("Parameter offset + len is " + 356 "greater than outbuf.length ."); 357 } 358 if (((ks + 7) / 8) > len) { 359 throw new SignatureException("Existing space in outbuf is less " 360 + "than the signature length would be."); 361 } 362 363 //Calculate the Signature with sign() 364 byte[] result = sign(); 365 366 //Copy the Signature into the outbuf starting at offset. 367 System.arraycopy(result, 0, outbuf, offset, result.length); 368 369 //Return the number of bytes placed into outbuf. 370 return result.length; 371 } 372 373 /** 374 * Verifies the passed-in signature. 375 * 376 * @param sigBytes the signature bytes to be verified. 377 * 378 * @return true if the signature was verified, false if not. 379 * 380 * @throws SignatureException if the engine is not initialized 381 * properly, or the passed-in signature is improperly encoded or 382 * of the wrong type, etc. 383 */ 384 boolean verify(byte[] sigBytes) throws SignatureException { 385 if (this.state != State.VERIFY) { 386 throw new SignatureException("Signature is not in VERIFY state."); 387 } 388 if (sigBytes == null) { 389 throw new NullPointerException("Parameter signBytes is null."); 390 } 391 if (this.mb.isEmpty()) { 392 throw new SignatureException("You have to add at least one byte " + 393 "to verify a message."); 394 } 395 396 try { 397 ISO9796Part1BitString sigma = 398 new ISO9796Part1BitString (sigBytes, this.ks); 399 400 ISO9796Part1BitString recoveredMessageDigest = 401 this.codec.decodeSignature(sigma); 402 403 if (recoveredMessageDigest == null) { 404 return false; 405 406 } else { //(message != null) 407 if (recoveredMessageDigest.equals(this.mb.fetch())) { 408 return true; 409 } else { 410 return false; 411 } 412 } 413 } finally { 414 //If something goes wrong we should reset the mb without fail! 415 //Also, if nothing goes wrong we should reset the mb too. 416 this.mb.reset(); 417 } 418 } 419 420 /** 421 * Verifies the passed-in signature in the specified array 422 * of bytes, starting at the specified offset. 423 * 424 * <p> Note: Subclasses should overwrite the default implementation. 425 * 426 * 427 * @param sigBytes the signature bytes to be verified. 428 * @param offset the offset to start from in the array of bytes. 429 * @param leng the number of bytes to use, starting at offset. 430 * 431 * @return true if the signature was verified, false if not. 432 * 433 * @throws SignatureException if the engine is not initialized 434 * properly, or the passed-in signature is improperly encoded or 435 * of the wrong type, etc. 436 */ 437 boolean verify(byte[] sigBytes, int offset, int len) 438 throws SignatureException { 439 if (this.state != State.VERIFY) { 440 throw new SignatureException("Signature is not in VERIFY state."); 441 } 442 if (sigBytes == null) { 443 throw new NullPointerException("Parameter signBytes is null."); 444 } 445 if (offset < 0) { 446 throw new IllegalArgumentException("Parameter offset is less " + 447 "than zero."); 448 } 449 if (len < 0) { 450 throw new IllegalArgumentException("Parameter len is less " + 451 "than zero."); 452 } 453 if (offset + len > sigBytes.length) { 454 throw new IllegalArgumentException("Parameter offset + len is " + 455 "greater than outbuf.length ."); 456 } 457 if (((ks + 7) / 8) != len) { 458 throw new SignatureException("Signature in sigBytes is not " + 459 ((ks + 7) / 8) + "bytes long."); 460 } 461 462 //Create a temporaly byte array that holds the 'sigBytes'. 463 byte[] tempSigBytes = new byte[len]; 464 465 //Copy the 'sigBytes' to 'tempSigBytes'. 466 System.arraycopy(sigBytes, offset, tempSigBytes, 0, len); 467 468 //Invoke the verify(byte[]) method with the 'tempSigBytesArray'. 469 return verify(tempSigBytes); 470 } 471 472 /** 473 * <p>This method is overridden by providers to initialize 474 * this signature engine with the specified parameter set. 475 * 476 * @param params the parameters 477 * 478 * @exception UnsupportedOperationException if this method is not 479 * overridden by a provider 480 * 481 * @throws InvalidAlgorithmParameterException if this method is 482 * overridden by a provider and the the given parameters 483 * are inappropriate for this signature engine 484 */ 485 void setParameter(AlgorithmParameterSpec params) 486 throws InvalidAlgorithmParameterException { 487 throw new UnsupportedOperationException("AlgorithmParameters are not " + 488 "supported for this signature."); 489 } 490 491 /** 492 * <p>This method is overridden by providers to return the 493 * parameters used with this signature engine, or null 494 * if this signature engine does not use any parameters. 495 * 496 * <p>The returned parameters may be the same that were used to initialize 497 * this signature engine, or may contain a combination of default and 498 * randomly generated parameter values used by the underlying signature 499 * implementation if this signature engine requires algorithm parameters 500 * but was not initialized with any. 501 * 502 * @return the parameters used with this signature engine, or null if this 503 * signature engine does not use any parameters 504 * 505 * @throws UnsupportedOperationException if this method is 506 * not overridden by a provider 507 */ 508 AlgorithmParameters getParameters() { 509 throw new UnsupportedOperationException("AlgorithmParameters are not " + 510 "supported for this signature."); 511 } 512 513 /** Type safe enum for the enclosing class object state. */ 514 private final static class State { 515 /** Name odf the state. */ 516 private final String name; 517 518 /** Constructor need only to called within this class. */ 519 private State(String name) { 520 this.name = name; 521 } 522 523 /** 524 * Returns a string representation of the object. 525 * 526 * @return a string representation of the object. 527 */ 528 public String toString() { 529 return this.name; 530 } 531 532 /** State constante if the enclosing class isn't initialized. */ 533 private static final State UNINITIALIZED = 534 new State("Uninitialized"); 535 536 /** State constante if the enclossing class is in Sign mode. */ 537 private static final State SIGN = new State("Sign"); 538 539 /** State constante if the enclossing class is in Verify mode. */ 540 private static final State VERIFY = new State("Verify"); 541 } 542 543 } 544
|
ISO9796Part1WithRSASignatureImpl |
|