|
RSACipherImpl |
|
1 /* $RCSfile: RSACipherImpl.java,v $ 2 * $Revision: 1.5 $ 3 * $Date: 2002/11/23 11:09:57 $ 4 * $Author: uwe_guenther $ 5 * $State: Exp $ 6 * 7 * Created on December 1, 2001 1: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.math.BigInteger; 35 import java.security.AlgorithmParameters; 36 import java.security.InvalidAlgorithmParameterException; 37 import java.security.InvalidKeyException; 38 import java.security.Key; 39 import java.security.NoSuchAlgorithmException; 40 import java.security.SecureRandom; 41 import java.security.interfaces.RSAKey; 42 import java.security.interfaces.RSAPrivateCrtKey; 43 import java.security.interfaces.RSAPrivateKey; 44 import java.security.interfaces.RSAPublicKey; 45 import java.security.spec.AlgorithmParameterSpec; 46 47 import javax.crypto.BadPaddingException; 48 import javax.crypto.Cipher; 49 import javax.crypto.IllegalBlockSizeException; 50 import javax.crypto.NoSuchPaddingException; 51 import javax.crypto.ShortBufferException; 52 53 import de.cscc.crypto.util.BigIntegerUtil; 54 55 /** 56 * RSACipherImpl Class. 57 * 58 * @author <a href=mailto:uwe@cscc.de>Uwe Günther</a> 59 * @version $Revision: 1.5 $ 60 */ 61 final class RSACipherImpl { 62 63 private SecureRandom random = new SecureRandom(); 64 65 private boolean initialized = false; 66 67 private int opmode; 68 69 /** RSAKey for the Cipher Object */ 70 private RSAKey key; 71 72 //not yet implemented (needed for update and doFinal) 73 private byte[] inputBuffer; 74 private int inputBufferCounter; 75 76 RSACipherImpl() {} 77 78 /** 79 * Returns a string representation of the object. 80 * 81 * @return a string representation of the object. 82 */ 83 public String toString() { 84 return "[RSA-Cipher]"; 85 } 86 87 /** 88 * Sets the mode of this cipher. 89 * @param mode the cipher mode. 90 * @throws NoSuchAlgorithmException if the requested cipher mode does not exist. 91 */ 92 void setMode(String mode) throws NoSuchAlgorithmException { 93 throw new NoSuchAlgorithmException("No Feedback mode supported."); 94 } 95 96 /** 97 * Sets the padding mechanism of this cipher. 98 * 99 * @param padding the padding mechanism. 100 * @throws NoSuchPaddingException if the requested padding mechanism does not exist. 101 */ 102 void setPadding(String padding) 103 throws NoSuchPaddingException { 104 throw new NoSuchPaddingException("No Padding Supported."); 105 } 106 107 /** 108 * Initializes this cipher with a key and a source of randomness. 109 * 110 * @param opmode the operation mode of this cipher. 111 * This is one of the following: 112 * javax.crypto.Cipher.ENCRYPT_MODE 113 * javax.crypto.Cipher.DECRYPT_MODE 114 * javax.crypto.Cipher.WRAP_MODE 115 * javax.crypto.Cipher.UNWRAP_MODE 116 * @param key the key to encrypt or to decrypt. 117 * @param random the source of randomness. 118 * @throws InvalidKeyException if the given key is inappropriate for 119 * initializing this cipher, this means if the key does not match to 120 * the specific opmode. 121 * @throws NullPointerException if key is null. 122 */ 123 void init(int opmode, Key key, SecureRandom random) 124 throws InvalidKeyException { 125 if (key == null) { 126 throw new NullPointerException("Prameter key is null."); 127 } 128 129 //We use only keys of the JHBCI Provider, so if you want to 130 //use other keys,you have to convert them with the RSAKeyFactory. 131 //We do this, because other RSAKeys may be insecure. 132 if (opmode == Cipher.ENCRYPT_MODE) { 133 this.opmode = Cipher.ENCRYPT_MODE; 134 if (key instanceof RSAPublicKeyImpl) { 135 this.key = (RSAKey) key; 136 } else { 137 throw new InvalidKeyException( 138 "Key does not match to opmode constant."); 139 } 140 } else if (opmode == Cipher.WRAP_MODE) { 141 this.opmode = Cipher.WRAP_MODE; 142 if (key instanceof RSAPublicKeyImpl) { 143 this.key = (RSAKey) key; 144 } else { 145 throw new InvalidKeyException( 146 "Key does not match to opmode constant."); 147 } 148 } else if (opmode == Cipher.DECRYPT_MODE) { 149 this.opmode = Cipher.DECRYPT_MODE; 150 if (key instanceof RSAPrivateCrtKeyImpl) { 151 this.key = (RSAKey) key; 152 } else if (key instanceof RSAPrivateKeyImpl) { 153 this.key = (RSAKey) key; 154 } else { 155 throw new InvalidKeyException( 156 "Key does not match to opmode constant."); 157 } 158 } else if (opmode == Cipher.UNWRAP_MODE) { 159 this.opmode = Cipher.UNWRAP_MODE; 160 if (key instanceof RSAPrivateCrtKeyImpl) { 161 this.key = (RSAKey) key; 162 } else if (key instanceof RSAPrivateKeyImpl) { 163 this.key = (RSAKey) key; 164 } else { 165 throw new InvalidKeyException( 166 "Key does not match to opmode constant."); 167 } 168 } else { 169 throw new IllegalArgumentException("Illegal opmode constant."); 170 } 171 if (random != null) { 172 this.random = random; 173 } 174 this.initialized = true; //set to true before call engineGetBlockSize 175 176 this.inputBuffer = new byte [getBlockSize()]; 177 this.inputBufferCounter = 0; 178 } 179 180 /** 181 * Initializes this cipher with a key, a set of algorithm parameters, 182 * and a source of randomness. 183 * 184 * @param opmode the operation mode of this cipher. 185 * This is one of the following: 186 * javax.crypto.Cipher.ENCRYPT_MODE 187 * javax.crypto.Cipher.DECRYPT_MODE 188 * javax.crypto.Cipher.WRAP_MODE 189 * javax.crypto.Cipher.UNWRAP_MODE 190 * @param key the key to encrypt or to decrypt. 191 * @param params the algorithm paramter. 192 * @param random the source of randomness. 193 * @throws InvalidKeyException if the given key is inappropriate for 194 * initializing this cipher. 195 * @throws InvalidAlgorithmParameterException if params isn't null, because 196 * we don't support AlgorithmParameters. 197 */ 198 void init(int opmode, Key key, AlgorithmParameters params, 199 SecureRandom random) 200 throws InvalidKeyException, InvalidAlgorithmParameterException { 201 if (params != null) { 202 throw new InvalidAlgorithmParameterException("Parameter params " + 203 "isn't null. We currently don't support AlgortihmParameters."); 204 } 205 init(opmode, key, random); 206 } 207 208 /** 209 * Initializes this cipher with a key, a set of algorithm parameters, 210 * and a source of randomness. 211 * 212 * @param opmode the operation mode of this cipher. 213 * This is one of the following: 214 * javax.crypto.Cipher.ENCRYPT_MODE 215 * javax.crypto.Cipher.DECRYPT_MODE 216 * javax.crypto.Cipher.WRAP_MODE 217 * javax.crypto.Cipher.UNWRAP_MODE 218 * @param key the key to encrypt or to decrypt. 219 * @param params the algorithm paramter. 220 * @param random the source of randomness. 221 * @throws InvalidKeyException if the given key is inappropriate for 222 * initializing this cipher. 223 * @throws InvalidAlgorithmParameterException if params isn't null, because 224 * we don't support AlgorithmParameterSpecs. 225 */ 226 void init(int opmode, Key key, AlgorithmParameterSpec params, 227 SecureRandom random) 228 throws InvalidKeyException, InvalidAlgorithmParameterException { 229 if (params != null) { 230 throw new InvalidAlgorithmParameterException("Parameter params " + 231 "isn't null. We currently don't support AlgortihmParameterSpecs."); 232 } 233 init(opmode, key, random); 234 } 235 236 /** 237 * Continues a multiple-part encryption or decryption operation 238 * (depending on how this cipher was initialized), processing another data 239 * part. 240 * 241 * @param input the input buffer. 242 * @param inputOffset the offset in input where the input starts. 243 * @param inputLen the input length. 244 * @throws IllegalStateException if the Cipher was not initialized, or you 245 * invoke this method in WRAP_MODE or UNWRAP_MODE. 246 * @return the new buffer with the result, or null if the 247 * underlying cipher is a block cipher and the input 248 * data is too short to result in a new block. 249 */ 250 byte[] update(byte[] input, int inputOffset, int inputLen) { 251 if (this.initialized == false) { 252 throw new IllegalStateException("Cipher not initialized"); 253 } 254 if (this.opmode == Cipher.ENCRYPT_MODE) { 255 //Put here code for encryption and remove the exception. 256 throw new UnsupportedOperationException( 257 "We support only Key wrap and Key unwrap."); 258 259 } else if (this.opmode == Cipher.DECRYPT_MODE) { 260 //Put here code for decryption and remove the exception. 261 throw new UnsupportedOperationException( 262 "We support only Key wrap and Key unwrap."); 263 264 } else { 265 //Wrong opmode, we lose. 266 throw new IllegalStateException("Cipher has unappropriate " + 267 "opmode , to invoke this method."); 268 } 269 } 270 271 /** 272 * Continues a multiple-part encryption or decryption operation 273 * (depending on how this cipher was initialized), processing another data 274 * part. 275 * 276 * @param input the input buffer. 277 * @param inputOffset the offset in input where the input starts. 278 * @param inputLen the input length. 279 * @param output the buffer for the result. 280 * @param outputOffset the offset in output where the result is stored. 281 * @throws ShortBufferException if the given output buffer is too small to 282 * hold the result. 283 * @throws IllegalStateException if the Cipher was not initialized, or you 284 * invoke this method in WRAP_MODE or UNWRAP_MODE. 285 * @return the number of bytes stored in output 286 */ 287 int update(byte[] input, int inputOffset, int inputLen, 288 byte[] output, int outputOffset) 289 throws ShortBufferException { 290 if (this.initialized == false) { 291 throw new IllegalStateException("Cipher not initialized"); 292 } 293 if (this.opmode == Cipher.ENCRYPT_MODE) { 294 //Put here code for encryption and remove the exception. 295 throw new UnsupportedOperationException( 296 "We support only Key wrap and Key unwrap."); 297 298 } else if (this.opmode == Cipher.DECRYPT_MODE) { 299 //Put here code for decryption and remove the exception. 300 throw new UnsupportedOperationException( 301 "We support only Key wrap and Key unwrap."); 302 303 } else { 304 //Wrong opmode, we lose. 305 throw new IllegalStateException("Cipher has unappropriate " + 306 "opmode , to invoke this method."); 307 } 308 } 309 310 311 /** 312 * Encrypts or decrypts data in a single-part operation, or finishes a 313 * multiple-part operation. 314 * 315 * @param input the input buffer. 316 * @param inputOffset the offset in input where the input starts. 317 * @param inputLen the input length. 318 * @throws IllegalBlockSizeException if this cipher is a block cipher, no padding 319 * has been requested (only in encryption mode), 320 * and the total input length of the data processed 321 * by this cipher is not a multiple of block size. 322 * @throws BadPaddingException if this cipher is in decryption mode, 323 * and (un)padding has been requested, 324 * but the decrypted data is not bounded 325 * by the appropriate padding bytes. 326 * @throws IllegalStateException if the Cipher was not initialized, or you 327 * invoke this method in WRAP_MODE or UNWRAP_MODE. 328 * @return the new buffer with the finally result. 329 */ 330 byte[] doFinal(byte[] input, int inputOffset, int inputLen) 331 throws IllegalBlockSizeException, BadPaddingException { 332 if (this.initialized == false) { 333 throw new IllegalStateException("Cipher not initialized"); 334 } 335 if (this.opmode == Cipher.ENCRYPT_MODE) { 336 //Put here code for encryption and remove the exception. 337 throw new UnsupportedOperationException( 338 "We support only Key wrap and Key unwrap."); 339 340 } else if (this.opmode == Cipher.DECRYPT_MODE) { 341 //Put here code for decryption and remove the exception. 342 throw new UnsupportedOperationException( 343 "We support only Key wrap and Key unwrap."); 344 345 } else { 346 //Wrong opmode, we lose. 347 throw new IllegalStateException("Cipher has unappropriate " + 348 "opmode , to invoke this method."); 349 } 350 } 351 352 353 /** 354 * Encrypts or decrypts data in a single-part operation, or finishes a 355 * multiple-part operation. 356 * 357 * @param input the input buffer. 358 * @param inputOffset the offset in input where the input starts. 359 * @param inputLen the input length. 360 * @param output the buffer for the finally result. 361 * @param outputOffset the offset in output where the result is stored. 362 * @throws ShortBufferException if the given output buffer is too small to 363 * hold the result. 364 * @throws IllegalBlockSizeException if this cipher is a block cipher, no padding 365 * has been requested (only in encryption mode), 366 * and the total input length of the data processed 367 * by this cipher is not a multiple of block size. 368 * @throws BadPaddingException if this cipher is in decryption mode, 369 * and (un)padding has been requested, 370 * but the decrypted data is not bounded 371 * by the appropriate padding bytes. 372 * @throws IllegalStateException if the Cipher was not initialized, or you 373 * invoke this method in WRAP_MODE or UNWRAP_MODE. 374 * @return the number of bytes stored in output. 375 */ 376 int doFinal(byte[] input, int inputOffset, int inputLen, 377 byte[] output, int outputOffset) throws ShortBufferException, 378 IllegalBlockSizeException, BadPaddingException { 379 if (this.initialized == false) { 380 throw new IllegalStateException("Cipher not initialized"); 381 } 382 if (this.opmode == Cipher.ENCRYPT_MODE) { 383 //Put here code for encryption and remove the exception. 384 throw new UnsupportedOperationException( 385 "We support only Key wrap and Key unwrap."); 386 387 } else if (this.opmode == Cipher.DECRYPT_MODE) { 388 //Put here code for decryption and remove the exception. 389 throw new UnsupportedOperationException( 390 "We support only Key wrap and Key unwrap."); 391 392 } else { 393 //Wrong opmode, we lose. 394 throw new IllegalStateException("Cipher has unappropriate " + 395 "opmode , to invoke this method."); 396 } 397 } 398 399 400 /** 401 * Wrap a key. 402 * 403 * @param key the key to be wrapped. 404 * @throws NullpointerException if <code>key.getEncoded()</code> is null. 405 * This means the key does not support encoding. 406 * @throws IllegalBlockSizeException if the unsigned number representation 407 * of the encoded key is equal or greater than the modulus of the RSAKey. 408 * @throws InvalidKeyException if it is impossible or unsafe to wrap the 409 * key with this cipher (e.g., a hardware 410 * public key is being passed to a 411 * software-only cipher). 412 * @throws IllegalStateException if the Cipher was not initialized, or you 413 * invoke this method in ENCRYPT_MODE or DECRTYPT_MODE. 414 * @return the wrapped key. 415 */ 416 byte[] wrap(Key key) throws IllegalBlockSizeException, InvalidKeyException { 417 if (this.initialized == false) { 418 throw new IllegalStateException("Cipher not initialized"); 419 } 420 if (key == null) { 421 throw new NullPointerException("Prameter key is null."); 422 } 423 if (this.opmode == Cipher.WRAP_MODE) { 424 //DES1Key 425 if (key.getAlgorithm().equalsIgnoreCase("DES1Key")) { 426 if (key.getFormat().equalsIgnoreCase("RAW")) { 427 //throws NullPointerException or IllegalBlockSizeException 428 return wrapKey(key); 429 } 430 //We are wrong... 431 throw new InvalidKeyException("Key has inappropriate encoding."); 432 } 433 //DESede2Key 434 if (key.getAlgorithm().equalsIgnoreCase("DESede2Key")) { 435 if(key.getFormat().equalsIgnoreCase("RAW")) { 436 //throws NullPointerException or IllegalBlockSizeException 437 return wrapKey(key); 438 } 439 //We are wrong... 440 throw new InvalidKeyException("Key has inappropriate encoding."); 441 } 442 //DESede3Key 443 if (key.getAlgorithm().equalsIgnoreCase("DESede3Key")) { 444 if(key.getFormat().equalsIgnoreCase("RAW")) { 445 //throws NullPointerException or IllegalBlockSizeException 446 return wrapKey(key); 447 } 448 //We are wrong... 449 throw new InvalidKeyException("Key has inappropriate encoding."); 450 } 451 //We are wong... 452 throw new InvalidKeyException("Key has inappropriate algorithm."); 453 } 454 //We are wrong... (default case - shouldn't really happen!) 455 //If we are ditching here, there are something wrong with initialization. 456 throw new IllegalStateException("Cipher contains an unappropriate " + 457 "opmode to invoke this method."); 458 } 459 460 /** 461 * Wraps a key. 462 * 463 * @throws NullpointerException if <code>key.getEncoded()</code> is null. 464 * This means the key does not support encoding. 465 * @throws IllegalBlockSizeException if the unsigned number representation 466 * of the encoded key is equal or greater than the modulus of the RSAKey. 467 * @return the wrapped key as byte array with an unsigned number in binary 468 * representation. 469 */ 470 private byte[] wrapKey(Key key) throws IllegalBlockSizeException { 471 byte[] encodedKey = key.getEncoded(); 472 if (encodedKey == null) { 473 throw new NullPointerException("Key does not support encoding."); 474 } 475 //Convert the binary representation of the key in non negative number. 476 BigInteger keyAsNumber = new BigInteger(1, encodedKey); 477 BigInteger modulus = this.key.getModulus(); 478 // keyAsNumber >= modulus 479 if (keyAsNumber.compareTo(modulus) >= 0) { 480 throw new IllegalBlockSizeException("Keys encoding data to large " + 481 "for the modulus."); 482 } 483 //Do RSA encryption: wrappedKey = keyAsNumber^publicExponent mod modulus 484 BigInteger publicExponent = ((RSAPublicKey) this.key).getPublicExponent(); 485 return BigIntegerUtil.toUnsignedByteArray( 486 keyAsNumber.modPow(publicExponent, modulus)); 487 } 488 489 /** 490 * Unwrap a previously wrapped key. 491 * 492 * @param wrappedKey the wrapped key to unwrap. 493 * @param wrappedKeyAlgorithm the algorithm associated with the key wrapped 494 * key. 495 * @param wrappedKeyType the type of the wrapped key. This is one of 496 * javax.crypto.Cipher.SECRET_KEY, 497 * javax.crypto.Cipher.PRIVATE_KEY, 498 * javax.crypto.Cipher.PUBLIC_KEY. 499 * @throws InvalidKeyException if wrappedKey does not represent a wrapped 500 * key, or if the algorithm associated with the wrapped key is different 501 * from wrappedKeyAlgorithm and/or its key type is different from 502 * wrappedKeyType. 503 * @throws NoSuchAlgorithmException if no installed providers can create 504 * keys for the wrappedKeyAlgorithm. 505 * @throws IllegalStateException if the Cipher was not initialized. 506 * @return the unwrapped key. 507 */ 508 Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, int wrappedKeyType) 509 throws InvalidKeyException, NoSuchAlgorithmException { 510 if (this.initialized == false) { 511 throw new IllegalStateException("Cipher not initialized"); 512 } 513 if (wrappedKey == null) { 514 throw new NullPointerException("Prameter wrappedKey is null."); 515 } 516 if (wrappedKeyAlgorithm == null) { 517 throw new NullPointerException("Prameter wrappedKeyAlgorithm is " + 518 "null."); 519 } 520 if (wrappedKeyType != Cipher.SECRET_KEY) { 521 throw new InvalidKeyException("Unsupported wrapped key type."); 522 } 523 if (this.opmode == Cipher.UNWRAP_MODE) { 524 if (wrappedKeyType == Cipher.SECRET_KEY) { 525 if (wrappedKeyAlgorithm.equalsIgnoreCase("DES1Key")) { 526 byte[] unwrappedKey = unwrapKey(wrappedKey); 527 //This check is addressed to the attack described by Dr. Ulrich Kuehn (many thanks!) 528 if (unwrappedKey.length > 8) { 529 throw new InvalidKeyException("Unwrapped DES1Key is longer than 64 bit."); 530 } 531 return new DES1KeySecretKeyImpl(unwrappedKey); 532 } 533 if (wrappedKeyAlgorithm.equalsIgnoreCase("DESede2Key")) { 534 byte[] unwrappedKey = unwrapKey(wrappedKey); 535 //This check is addressed to the attack described by Dr. Ulrich Kuehn (many thanks!) 536 if (unwrappedKey.length > 16) { 537 throw new InvalidKeyException("Unwrapped DESede2Key is longer than 128 bit."); 538 } 539 return new DESede2KeySecretKeyImpl(unwrappedKey); 540 } 541 if (wrappedKeyAlgorithm.equalsIgnoreCase("DESede3Key")) { 542 byte[] unwrappedKey = unwrapKey(wrappedKey); 543 //This check is addressed to the attack described by Dr. Ulrich Kuehn (many thanks!) 544 if (unwrappedKey.length > 24) { 545 throw new InvalidKeyException("Unwrapped DESede3Key is longer than 168 bit."); 546 } 547 return new DESede3KeySecretKeyImpl(unwrapKey(wrappedKey)); 548 } 549 //We are wrong... 550 throw new NoSuchAlgorithmException("Requested wrapped key " + 551 "algorithm not supported by the requested wrapped key type."); 552 } if (wrappedKeyType == Cipher.PUBLIC_KEY) { 553 // 554 //put here code for Public Key unwrapping 555 // 556 //We don't support public key unwrapping 557 throw new InvalidKeyException("Requested wrapped key type " + 558 "not supported."); 559 } if (wrappedKeyType == Cipher.PRIVATE_KEY) { 560 // 561 //put here code for Public Key unwrapping 562 // 563 //We don't support private key unwrapping 564 throw new InvalidKeyException("Requested wrapped key type " + 565 "not supported."); 566 } 567 //We are wrong... 568 throw new IllegalArgumentException("Cipher contains an unknown " + 569 "wrapped key type."); 570 } 571 //We are wrong... (default case - shouldn't really happen!) 572 //If we are ditching here, there are something wrong with initialization. 573 throw new IllegalStateException("Cipher contains an unappropriate " + 574 "opmode to invoke this method."); 575 } 576 577 578 /** 579 * Unwrap (decrypt) a wrappedKey in a byte array. 580 * 581 * @param wrapped key the wrapped key in its binary representation. 582 * @throws InvalidKeyException if the unsigned BigInteger representation of 583 * the wrappedKey byte array is equals or greater than the modulus of the 584 * RSAKey. 585 * @throws IllegalStateException if the internal key of the Cipher 586 * is inappropriate (Should not happen). 587 * @return the unwrapped key in its binary representation. 588 */ 589 private byte[] unwrapKey(byte[] wrappedKey) throws InvalidKeyException { 590 BigInteger wrappedKeyAsNumber = new BigInteger(1, wrappedKey); 591 BigInteger modulus = this.key.getModulus(); 592 if (wrappedKeyAsNumber.compareTo(modulus) >= 0) { 593 throw new InvalidKeyException("Wrapped key data data to " + 594 "large for the modulus."); 595 } 596 //Chinese remainder theorem RSA decryption 597 if (this.key instanceof RSAPrivateCrtKey) { 598 BigInteger primeP = 599 ((RSAPrivateCrtKey) this.key).getPrimeP(); 600 BigInteger primeQ = 601 ((RSAPrivateCrtKey) this.key).getPrimeQ(); 602 BigInteger primeExponentP = 603 ((RSAPrivateCrtKey) this.key).getPrimeExponentP(); 604 BigInteger primeExponentQ = 605 ((RSAPrivateCrtKey) this.key).getPrimeExponentQ(); 606 BigInteger crtCoefficient = 607 ((RSAPrivateCrtKey) this.key).getCrtCoefficient(); 608 609 BigInteger messageOne = 610 wrappedKeyAsNumber.modPow(primeExponentP, primeP); 611 BigInteger messageTwo = 612 wrappedKeyAsNumber.modPow(primeExponentQ, primeQ); 613 BigInteger h = 614 messageOne.subtract(messageTwo).multiply(crtCoefficient).mod(primeP); 615 BigInteger message = primeQ.multiply(h).add(messageTwo); 616 617 byte[] unWrappedKey = BigIntegerUtil.toUnsignedByteArray(message); 618 return unWrappedKey; 619 } 620 //original RSA decryption 621 if (this.key instanceof RSAPrivateKey) { 622 BigInteger privateExponent = 623 ((RSAPrivateKey) this.key).getPrivateExponent(); 624 BigInteger message = 625 wrappedKeyAsNumber.modPow(privateExponent, modulus); 626 byte[] unWrappedKey = BigIntegerUtil.toUnsignedByteArray(message); 627 return unWrappedKey; 628 } 629 //We are wrong... (default case - shouldn't really happen!) 630 //If we are ditching here, there are something wrong with initialization. 631 throw new IllegalStateException("Cipher contains inappropriate Key."); 632 } 633 634 /** 635 * Returns the block size (in bytes) that can be processed while a 636 * multipart cipher operation. 637 * 638 * @throws IllegalStateException if the Cipher was not initialized or a 639 * opmode does not match. 640 * @return the input block size (in bytes). 641 */ 642 int getBlockSize() { 643 //Input Block Size 644 if (this.initialized == false) { 645 throw new IllegalStateException("Cipher not initialized"); 646 } 647 //Encryption 648 if (this.opmode == Cipher.ENCRYPT_MODE) { 649 return (this.key.getModulus().bitLength() - 1) / 8; 650 } 651 if (this.opmode == Cipher.WRAP_MODE) { 652 return (this.key.getModulus().bitLength() - 1) / 8; 653 } 654 //Decryption 655 if (this.opmode == Cipher.DECRYPT_MODE) { 656 return (this.key.getModulus().bitLength() + 7) / 8; 657 } 658 if (this.opmode == Cipher.UNWRAP_MODE) { 659 return (this.key.getModulus().bitLength() + 7) / 8; 660 } 661 //We are wrong... 662 throw new IllegalStateException("Unknown opmode."); 663 } 664 665 /** 666 * Returns the length in bytes that an output buffer would need to be in 667 * order to hold the result of the next update or doFinal operation, given 668 * the input length inputLen (in bytes). 669 * 670 * @param inputLen the input length in bytes. 671 * @throws IllegalStateException if the Cipher was not initialized or a 672 * opmode does not match. 673 * @return the reqired output buffer size in bytes. 674 */ 675 int getOutputSize(int inputLen) { 676 /* 677 * In our case the output size is independend of the input length, 678 * because our ouput blocks have always a length that depends on the 679 * modulus bit length. 680 */ 681 682 //Output Block Size 683 if (this.initialized == false) { 684 throw new IllegalStateException("Cipher not initialized"); 685 } 686 //Encryption 687 if (this.opmode == Cipher.ENCRYPT_MODE) { 688 return (this.key.getModulus().bitLength() + 7) / 8; 689 } 690 if (this.opmode == Cipher.WRAP_MODE) { 691 return (this.key.getModulus().bitLength() + 7) / 8; 692 } 693 //Decryption 694 if (this.opmode == Cipher.DECRYPT_MODE) { 695 return (this.key.getModulus().bitLength() - 1) / 8; 696 } 697 if (this.opmode == Cipher.UNWRAP_MODE) { 698 return (this.key.getModulus().bitLength() - 1) / 8; 699 } 700 //We are wrong... 701 throw new IllegalStateException("Unknown opmode."); 702 } 703 704 /** 705 * Returns the key size of the given key object in bit. This method will be 706 * invoked trough the JCE before engineInit is invoked. 707 * 708 * @param key the key object. 709 * @throws InvalidKeyException if key is invalid. 710 * @return the key size of the given key object. 711 */ 712 int getKeySize(Key key) throws InvalidKeyException { 713 //We check only keys of the JHBCI Provider, so if you want to 714 //use other keys,you have to convert them with the RSAKeyFactory. 715 //We do this, because other RSAKeys may be insecure. 716 if (key instanceof RSAPublicKeyImpl) { 717 return ((RSAKey) key).getModulus().bitLength(); 718 } 719 if (key instanceof RSAPrivateKeyImpl) { 720 return ((RSAKey) key).getModulus().bitLength(); 721 } 722 if (key instanceof RSAPrivateCrtKeyImpl) { 723 return ((RSAKey) key).getModulus().bitLength(); 724 } 725 //We are wrong... 726 throw new InvalidKeyException("Inappropriate Key."); 727 } 728 729 /** 730 * Returns the parameters used with this cipher. 731 * 732 * @throws IllegalStateException if the Cipher was not initialized. 733 * @return the parameters used with this cipher, 734 * or null if this cipher does not use 735 * any parameters. 736 */ 737 AlgorithmParameters getParameters() { 738 if (this.initialized == false) { 739 throw new IllegalStateException("Cipher not initialized"); 740 } 741 return null; 742 } 743 744 /** 745 * Returns the initialization vector (IV) in a new buffer. 746 * 747 * @throws IllegalStateException if the Cipher was not initialized. 748 * @return the initialization vector in a new buffer, 749 * or null if the underlying algorithm does not 750 * use an IV, or if the IV has not yet been set. 751 */ 752 byte[] getIV() { 753 if (this.initialized == false) { 754 throw new IllegalStateException("Cipher not initialized"); 755 } 756 return null; 757 } 758 } 759
|
RSACipherImpl |
|