|
PaddingNoPadding |
|
1 /* $RCSfile: PaddingNoPadding.java,v $ 2 * $Revision: 1.11 $ 3 * $Date: 2002/11/23 11:09:56 $ 4 * $Author: uwe_guenther $ 5 * $State: Exp $ 6 * 7 * Created on August 19, 2001 4:29 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 javax.crypto.IllegalBlockSizeException; 35 import javax.crypto.ShortBufferException; 36 37 /** 38 * PaddingNoPadding Class. 39 * 40 * @author <a href=mailto:uwe@cscc.de>Uwe Günther</a> 41 * @version $Revision: 1.11 $ 42 */ 43 class PaddingNoPadding extends Padding { 44 45 /** 46 * The operation mode object (such as ECB, or CBC), that 47 * will be wrapped from this padding object. 48 */ 49 private OperationMode mode; 50 51 /** 52 * A single buffer to store unprocessed plaintext, 53 * while processing a block cipher. 54 */ 55 private PaddingSingleBuffer unprocessedPlainTextBuffer; 56 57 /** 58 * A single buffer to store unprocessed ciphertext, 59 * while processing a block cipher. 60 */ 61 private PaddingSingleBuffer unprocessedCipherTextBuffer; 62 63 /** 64 * Temporary buffer that will be used from al en- and decrypt methods 65 * to prvent exceive byt[] allocation in these methods. 66 */ 67 private byte[] tempBuffer; 68 69 70 /** Don't create an PaddingNoPadding with the default constructor */ 71 private PaddingNoPadding() {} 72 73 /** 74 * Constructs a new padding object, that wraps a operation mode 75 * object. 76 * 77 * @param mode the operation mode algorithm object that we wrap. 78 */ 79 public PaddingNoPadding(OperationMode mode){ 80 81 this.mode = mode; 82 this.unprocessedPlainTextBuffer = 83 new PaddingSingleBuffer(getBlockSize()); 84 this.unprocessedCipherTextBuffer = 85 new PaddingSingleBuffer(getBlockSize()); 86 87 this.tempBuffer = new byte[getBlockSize()]; 88 } 89 90 /** 91 * Returns a string representation of the object. 92 * 93 * @return a string representation of the object. 94 */ 95 public String toString() { 96 97 String returnValue = ""; 98 99 returnValue += "[mode: " + this.mode + "] "; 100 returnValue += "[unprocessedPlainTextBuffer: " + this.unprocessedPlainTextBuffer + "] "; 101 returnValue += "[unprocessedCipherTextBuffer: " + this.unprocessedCipherTextBuffer + "] "; 102 103 return returnValue; 104 } 105 106 /** 107 * Get the block size of the underlying mode object. 108 * 109 * @return the block size of the underlying mode object. 110 */ 111 public int getBlockSize() { 112 return mode.getBlockSize(); 113 } 114 115 /** 116 * Calculates the output size for a returned byted array, or 117 * the size for the output array that will 118 * be passed through updateEncryption(.....). 119 * 120 * @param inputLength the input length, that will be base for the 121 * calculation. 122 * @return the size for a returned byted array, or 123 * the size for the output array that will 124 * be passed through updateEncryption(.....). 125 */ 126 public int getUpdateEncryptionOutputSize(int inputLength) { 127 //Skip the rest if we divide with getBlockSize() 128 return ( 129 ( 130 this.unprocessedPlainTextBuffer.hasBytes() + inputLength 131 ) / getBlockSize() 132 ) * getBlockSize(); 133 } 134 135 /** 136 * Continues a multipart encryption operation, processing 137 * another data part. 138 * 139 * @param input plainText that should be encrypted. 140 * @param inputOffset the offset in input where the input starts. 141 * @param inputLength the input length. 142 * @throws IllegalArgumentException if <tt>input == null</tt>, 143 * <tt>inputOffset < 0</tt>, <tt>inputLength < 0</tt> or 144 * <tt>input.length < inputOffset+inputLength</tt>. 145 * @return the encrypted data, if there enough (at least one block size), 146 * or byte[0] otherwise. We aren't allowed to return null, like javadoc 147 * for CipherSpi this says, because the JCE 148 * (byte[] Cipher#update(byte[], int, int)) will throw a 149 * NullPointerException. 150 */ 151 public byte[] updateEncryption(byte[] input, int inputOffset, 152 int inputLength) { 153 //The next three if's are hte same as the JCE does check, 154 //but these checks are not documented, so we do check again. 155 if (input == null) { 156 throw new IllegalArgumentException("Bad Arguments."); 157 } 158 159 if (inputOffset < 0 || 160 inputLength < 0 || 161 input.length < (inputOffset+inputLength)) { 162 163 throw new IllegalArgumentException("Bad Arguments."); 164 } 165 166 ////if (inputLength == 0){ 167 //// return null; 168 ////} 169 170 171 byte[] output =null; 172 int outputOffset =0; 173 174 //Will be there some result, get space for the result output byte array. 175 ////if(getUpdateEncryptionOutputSize(inputLength) > 0){ 176 output = new byte[getUpdateEncryptionOutputSize(inputLength)]; 177 ////} 178 179 //Process the whole input. 180 for (int i = inputOffset; i < inputOffset+inputLength; i++) { 181 182 //Add every single byte to our unprocessedPlainTextBuffer. 183 this.unprocessedPlainTextBuffer.add(input[i]); 184 185 //If our unprocessedPlainTextBuffer is full process it and put 186 //the result into output. 187 if (this.unprocessedPlainTextBuffer.isFull()) { 188 189 //Process the unprocessedPlainTextBuffer and switch the 190 //outputOffset one block further. 191 try { 192 this.unprocessedPlainTextBuffer.fetch(this.tempBuffer, 0); 193 194 outputOffset += 195 this.mode.encrypt(this.tempBuffer, 0, output, outputOffset); 196 } catch (IllegalBlockSizeException cannothappen){ 197 throw new Error("Can not happen.", cannothappen); 198 } catch (ShortBufferException cannothappen){ 199 throw new Error("Can not happen.", cannothappen); 200 } 201 } 202 } 203 204 //Return the result as byte array, or byte[0] if there no result. 205 return output; 206 } 207 208 /** 209 * Continues a multipart encryption operation, processing 210 * another data part. 211 * 212 * @param input plainText that should be encrypted. 213 * @param inputOffset the offset in input where the input starts. 214 * @param inputLength the input length. 215 * @param output the buffer for the encrypted result. 216 * @param outputOffset the offset in output where the result is stored. 217 * @throws ShortBufferException if the usable range in the output buffer is 218 * to less. This means that the usable range must at least 219 * getUpdateEncryptionOutputSize(inputLength) bytes large. 220 * @throws IllegalArgumentException if <tt>input == null</tt>, 221 * <tt>inputOffset < 0</tt>, <tt>inputLength < 0</tt>, 222 * <tt>outputOffset < 0</tt> or <tt>input.length < 223 * inputOffset+inputLength</tt>. 224 * @return the number of bytes stored in output. 225 */ 226 public int updateEncryption(byte[] input, int inputOffset, int inputLength, 227 byte[] output, int outputOffset) throws ShortBufferException { 228 //The next three if's are the same as the JCE does check, 229 //but these checks are not documented, so we do check again. 230 if (input == null) { 231 throw new IllegalArgumentException("Bad Arguments."); 232 } 233 234 if (inputOffset < 0 || 235 inputLength < 0 || 236 outputOffset < 0 || 237 input.length < (inputOffset+inputLength)) { 238 239 throw new IllegalArgumentException("Bad Arguments."); 240 } 241 242 if (inputLength == 0) { 243 return 0; 244 } 245 246 247 //Check output for null. 248 if (output == null) { 249 throw new ShortBufferException( 250 "Output buffer should be (at least) " + 251 getUpdateEncryptionOutputSize(inputLength) + 252 " bytes or larger, but not null."); 253 } 254 255 //Check, if output is large enough. 256 if (getUpdateEncryptionOutputSize(inputLength) > output.length-outputOffset) { 257 throw new ShortBufferException( 258 "Usable byte range in output buffer is " + 259 (output.length-outputOffset) + " bytes large, but it should be " + 260 getUpdateEncryptionOutputSize(inputLength) + " bytes or larger."); 261 } 262 263 264 //Save outputOffset, to calc number of bytes stored in output. 265 int saveOutputOffset =outputOffset; 266 267 //Process the whole input. 268 for (int i = inputOffset; i < inputOffset+inputLength; i++) { 269 270 //Add every single byte to our unprocessedPlainTextBuffer. 271 this.unprocessedPlainTextBuffer.add(input[i]); 272 273 //If our unprocessedPlainTextBuffer is full process it and put the 274 //result into output. 275 if (this.unprocessedPlainTextBuffer.isFull()) { 276 277 //If one of the Exception, declared in the catch clause, was 278 //thrown, the cause is orginated here, so we catch it here. 279 try { 280 this.unprocessedPlainTextBuffer.fetch(this.tempBuffer, 0); 281 282 //Process our unprocessedPlainTextBuffer and add the number 283 //of new output bytes to outputOffset. 284 outputOffset += 285 this.mode.encrypt(this.tempBuffer, 0, output, outputOffset); 286 } catch (IllegalBlockSizeException cannothappen) { 287 throw new Error("Can not happen.", cannothappen); 288 } catch (ShortBufferException cannothappen) { 289 throw new Error("Can not happen.", cannothappen); 290 } 291 } 292 } 293 294 //Return the number of bytes stored in output. 295 return outputOffset - saveOutputOffset; 296 } 297 298 /** 299 * Calculates the output size for a returned byted array, or 300 * the size for the output array that will 301 * be passed through doFinalEncryption(.....). 302 * 303 * @param inputLength the input length, that will be base for the 304 * calculation. 305 * @return the size for a returned byted array, or 306 * the size for the output array that will 307 * be passed through doFinalEncryption(.....). 308 */ 309 public int getDoFinalEncryptionOutputSize(int inputLength) { 310 //getUpdateSize() + one block for the padding bytes. 311 return getUpdateEncryptionOutputSize(inputLength); 312 } 313 314 /** 315 * Checks if the result from buffer bytes and 316 * a given inputLength is a multiple of the 317 * block size of the underlying mode object. 318 * 319 * @param inputLength the input length, that will be base for the 320 * verification. 321 * @return true if the result from buffer bytes and 322 * a given inputLength is a multiple of the 323 * block size of the underlying mode object, 324 * false otherwise. 325 */ 326 private boolean isPlainTextBufferAndInputLengthMultipleOfBlockSize( 327 int inputLength) { 328 return ( 329 this.unprocessedPlainTextBuffer.hasBytes() + inputLength 330 ) % getBlockSize() == 0; 331 } 332 333 /** 334 * Encrypts data in a single part operation, or finishes 335 * a multipart encryption. 336 * 337 * @param input plainText that should be encrypted. 338 * @param inputOffset the offset in input where the input starts. 339 * @param inputLength the input length. 340 * @throws IllegalBlockSizeException If all processed bytes in a multipart decryption 341 * are not multiple of operation mode block size. 342 * @throws IllegalArgumentException if <tt>input == null</tt>, 343 * <tt>inputOffset < 0</tt>, <tt>inputLength < 0</tt>, 344 * or <tt>input.length < inputOffset+inputLength</tt>. 345 * @return the padded and encrypted data. 346 */ 347 public byte[] doFinalEncryption(byte[] input, int inputOffset, 348 int inputLength) throws IllegalBlockSizeException { 349 //The next three if's are hte same as the JCE does check, 350 //but these checks are not documented, so we do check again. 351 if (input == null && inputOffset == 0 && inputLength == 0) { 352 //At these point the JCE byte[] doFinal() was invoked. 353 } else { 354 355 if (input == null) { 356 throw new IllegalArgumentException("Bad Arguments."); 357 } 358 359 if (inputOffset < 0 || 360 inputLength < 0 || 361 input.length < (inputOffset+inputLength)) { 362 363 throw new IllegalArgumentException("Bad Arguments."); 364 } 365 } 366 367 if (isPlainTextBufferAndInputLengthMultipleOfBlockSize(inputLength) == false) { 368 throw new IllegalBlockSizeException( 369 "Input length not multiple of " + getBlockSize() + " bytes."); 370 } 371 372 //Get space for the result output byte array. 373 byte[] output = new byte[getDoFinalEncryptionOutputSize(inputLength)]; 374 int outputOffset =0; 375 376 //Process the whole input. 377 for (int i = inputOffset; i < inputOffset+inputLength; i++) { 378 379 //Add every single byte to our unprocessedPlainTextBuffer. 380 this.unprocessedPlainTextBuffer.add(input[i]); 381 382 //If our unprocessedPlainTextBuffer is full process it and put 383 //the result into output. 384 if (this.unprocessedPlainTextBuffer.isFull()) { 385 386 //If one of the Exception, declared in the catch clause, was 387 //thrown, the cause is orginated here, so we catch it here. 388 try { 389 this.unprocessedPlainTextBuffer.fetch(this.tempBuffer, 0); 390 391 //Process our unprocessedPlainTextBuffer and add the number 392 //of new output bytes to outputOffset. 393 outputOffset += 394 this.mode.encrypt(this.tempBuffer, 0, output, outputOffset); 395 } catch (IllegalBlockSizeException cannothappen) { 396 throw new Error("Can not happen.", cannothappen); 397 } catch (ShortBufferException cannothappen) { 398 throw new Error("Can not happen.", cannothappen); 399 } 400 } 401 } 402 403 //Now all things are done, so we can reset the mode object to reuse it. 404 this.mode.resetToIv(); 405 406 //Return the result as byte array, or null if there no result. 407 return output; 408 } 409 410 /** 411 * Encrypts data in a single part operation, or finishes 412 * a multipart encryption. 413 * 414 * @param input plainText that should be encrypted. 415 * @param inputOffset the offset in input where the input starts. 416 * @param inputLength the input length. 417 * @param output the buffer for the padded and encrypted result. 418 * @param outputOffset the offset in output where the result is stored. 419 * @throws IllegalBlockSizeException If all processed bytes in a multipart decryption 420 * are not multiple of operation mode block size. 421 * @throws ShortBufferException if the usable range in the output buffer is 422 * to less. This means that the usable range must at least 423 * getDoFinalEncryptionOutputSize(inputLength) bytes large. 424 * @throws IllegalArgumentException if <tt>input == null</tt>, 425 * <tt>inputOffset < 0</tt>, <tt>inputLength < 0</tt>, 426 * <tt>outputOffset < 0</tt> or <tt>input.length < 427 * inputOffset+inputLength</tt>. 428 * @return the number of bytes stored in output. 429 */ 430 public int doFinalEncryption(byte[] input, int inputOffset, int inputLength, 431 byte[] output, int outputOffset) 432 throws IllegalBlockSizeException, ShortBufferException { 433 //The next three if's are hte same as the JCE does check, 434 //but these checks are not documented, so we do check again. 435 if (input == null && inputOffset == 0 && inputLength == 0) { 436 //At these point the JCE 437 //byte[] doFinal(byte[] output, int outputOffset) was invoked. 438 } else { 439 440 if (input == null) { 441 throw new IllegalArgumentException("Bad Arguments."); 442 } 443 444 if (inputOffset < 0 || 445 inputLength < 0 || 446 outputOffset < 0 || 447 input.length < (inputOffset+inputLength)) { 448 449 throw new IllegalArgumentException("Bad Arguments."); 450 } 451 } 452 453 if (isPlainTextBufferAndInputLengthMultipleOfBlockSize(inputLength) == false) { 454 throw new IllegalBlockSizeException( 455 "Input length not multiple of " + getBlockSize() + " bytes."); 456 } 457 458 //Check output for null. 459 if (output == null) { 460 throw new ShortBufferException( 461 "Output buffer should be (at least) " + 462 getDoFinalEncryptionOutputSize(inputLength) + 463 " bytes or larger, but not null."); 464 } 465 466 //Check, if output is large enough. 467 if (getUpdateEncryptionOutputSize(inputLength) > output.length-outputOffset) { 468 throw new ShortBufferException( 469 "Usable byte range in output buffer is " + 470 (output.length-outputOffset) + " bytes large, but it should be " + 471 getDoFinalEncryptionOutputSize(inputLength) + " bytes or larger."); 472 } 473 474 475 //Save outputOffset, to calc number of bytes stored in output. 476 int saveOutputOffset = outputOffset; 477 478 //Process the whole input. 479 for (int i = inputOffset; i < inputOffset+inputLength; i++) { 480 481 //Add every single byte to our unprocessedPlainTextBuffer. 482 this.unprocessedPlainTextBuffer.add(input[i]); 483 484 //If our unprocessedPlainTextBuffer is full process it and put the 485 //result into output. 486 if (this.unprocessedPlainTextBuffer.isFull()) { 487 488 //If one of the Exception, declared in the catch clause, was 489 //thrown, the cause is orginated here, so we catch it here. 490 try { 491 this.unprocessedPlainTextBuffer.fetch(this.tempBuffer, 0); 492 493 //Process our unprocessedPlainTextBuffer and add the number 494 //of new output bytes to outputOffset. 495 outputOffset += 496 this.mode.encrypt(this.tempBuffer, 0, output, outputOffset); 497 } catch (IllegalBlockSizeException cannothappen){ 498 throw new Error("Can not happen.", cannothappen); 499 } 500 } 501 } 502 503 //Now all things are done, so we can reset the mode object to reuse it. 504 this.mode.resetToIv(); 505 506 //Return the number of bytes stored in output. 507 return outputOffset - saveOutputOffset; 508 } 509 510 /** 511 * Calculates the output size for a returned byted array, or 512 * the size for the output array that will 513 * be passed through updateDecryption(.....). 514 * 515 * @param inputLength the input length, that will be base for the 516 * calculation. 517 * @return the size for a returned byted array, or 518 * the size for the output array that will 519 * be passed through updateDecryption(.....). 520 */ 521 public int getUpdateDecryptionOutputSize(int inputLength) { 522 //Skip the rest if we divide with getBlockSize() 523 return ( 524 ( 525 this.unprocessedCipherTextBuffer.hasBytes() + inputLength 526 ) / getBlockSize() 527 ) * getBlockSize(); 528 } 529 530 /** 531 * Continues a multipart decryption operation, processing 532 * another data part. 533 * 534 * @param input padded cipherText that should be decrypted. 535 * @param inputOffset the offset in input where the input starts. 536 * @param inputLength the input length. 537 * @return the decrypted data, if there enough (at least one block size + 538 * one byte), or new byte[0] otherwise. We aren't allowed to return null, 539 * like javadoc for CipherSpi this says, because the JCE 540 * (byte[] Cipher#update(byte[], int, int)) will throw a 541 * NullPointerException. 542 * @throws IllegalArgumentException if <tt>input == null</tt>, 543 * <tt>inputOffset < 0</tt>, <tt>inputLength < 0</tt>, 544 * or <tt>input.length < 545 * inputOffset+inputLength</tt>. 546 */ 547 public byte[] updateDecryption(byte[] input, int inputOffset, 548 int inputLength) { 549 //The next three if's are the same as the JCE does check, 550 //but these checks are not documented, so we do check again. 551 if (input == null) { 552 throw new IllegalArgumentException("Bad Arguments."); 553 } 554 555 if (inputOffset < 0 || 556 inputLength < 0 || 557 input.length < (inputOffset+inputLength)) { 558 559 throw new IllegalArgumentException("Bad Arguments."); 560 } 561 562 ////if (inputLength == 0){ 563 //// return null; 564 ////} 565 566 567 byte[] output = null; 568 int outputOffset = 0; 569 570 //Will be there some result, get space for the result output byte array. 571 ////if(getUpdateDecryptionOutputSize(inputLength) > 0){ 572 output = new byte[getUpdateDecryptionOutputSize(inputLength)]; 573 ////} 574 575 //Process the whole input. 576 for (int i = inputOffset; i < inputOffset+inputLength; i++) { 577 578 //Add every single byte to our unprocessedCipherTextBuffer. 579 this.unprocessedCipherTextBuffer.add(input[i]); 580 581 //If our unprocessedCipherTextBuffer is full, process it 582 //and put the result into output. 583 if (this.unprocessedCipherTextBuffer.isFull()) { 584 585 //If one of the Exception, declared in the catch clause, was 586 //thrown, the cause is orginated here, so we catch it here. 587 try { 588 this.unprocessedCipherTextBuffer.fetch(this.tempBuffer, 0); 589 590 //Process our unprocessedCipherTextBuffer and add the number 591 //of new output bytes to outputOffset. 592 outputOffset += 593 this.mode.decrypt(this.tempBuffer, 0, output, outputOffset); 594 } catch (IllegalBlockSizeException cannothappen) { 595 throw new Error("Can not happen.", cannothappen); 596 } catch (ShortBufferException cannothappen) { 597 throw new Error("Can not happen.", cannothappen); 598 } 599 } 600 } 601 602 //Return the result as byte array, or byte[0] if there no result. 603 return output; 604 } 605 606 /** 607 * Continues a multipart decryption operation, processing 608 * another data part. 609 * 610 * @param input padded cipherText that should be decrypted. 611 * @param inputOffset the offset in input where the input starts. 612 * @param inputLength the input length. 613 * @param output the buffer for the decrypted result. 614 * @param outputOffset the offset in output where the result is stored. 615 * @throws ShortBufferException if the usable range in the output buffer is 616 * to less. This means that the usable range must at least 617 * getUpdateDecryptionOutputSize(inputLength) bytes large. 618 * @throws IllegalArgumentException if <tt>input == null</tt>, 619 * <tt>inputOffset < 0</tt>, <tt>inputLength < 0</tt>, 620 * <tt>outputOffset < 0</tt> or <tt>input.length < 621 * inputOffset+inputLength</tt>. 622 * @return the number of bytes stored in output. 623 */ 624 public int updateDecryption(byte[] input, int inputOffset, int inputLength, 625 byte[] output, int outputOffset) throws ShortBufferException { 626 //The next three if's are hte same as the JCE does check, 627 //but these checks are not documented, so we do check again. 628 if (input == null) { 629 throw new IllegalArgumentException("Bad Arguments."); 630 } 631 632 if (inputOffset < 0 || 633 inputLength < 0 || 634 outputOffset < 0 || 635 input.length < (inputOffset+inputLength)) { 636 637 throw new IllegalArgumentException("Bad Arguments."); 638 } 639 640 if (inputLength == 0) { 641 return 0; 642 } 643 644 645 //Check output for null. 646 if (output == null) { 647 throw new ShortBufferException( 648 "Output buffer should be (at least) " + 649 getUpdateDecryptionOutputSize(inputLength) + 650 " bytes or larger, but not null."); 651 } 652 653 //Check, if output is large enough. 654 if (getUpdateDecryptionOutputSize(inputLength) > output.length-outputOffset){ 655 throw new ShortBufferException( 656 "Usable byte range in output buffer is " + 657 (output.length-outputOffset) + " bytes large, but it should be " + 658 getUpdateDecryptionOutputSize(inputLength) + " bytes or larger."); 659 } 660 661 662 //Save outputOffset, to calc number of bytes stored in output. 663 int saveOutputOffset =outputOffset; 664 665 //Process the whole input. 666 for (int i = inputOffset; i < inputOffset+inputLength; i++) { 667 668 //Add every single byte to our unprocessedCipherTextBuffer. 669 this.unprocessedCipherTextBuffer.add(input[i]); 670 671 //If our unprocessedCipherTextBuffer is full, process it 672 //and put the result into output. 673 if (this.unprocessedCipherTextBuffer.isFull()) { 674 675 //If one of the Exception, declared in the catch clause, was 676 //thrown, the cause is orginated here, so we catch it here. 677 try { 678 this.unprocessedCipherTextBuffer.fetch(this.tempBuffer, 0); 679 680 //Process our unprocessedCipherTextBuffer and add the number 681 //of new output bytes to outputOffset. 682 outputOffset += 683 this.mode.decrypt(this.tempBuffer, 0, output, outputOffset); 684 } catch (IllegalBlockSizeException cannothappen) { 685 throw new Error("Can not happen.", cannothappen); 686 } catch (ShortBufferException cannothappen) { 687 throw new Error("Can not happen.", cannothappen); 688 } 689 } 690 } 691 692 //Return the number of bytes stored in output. 693 return outputOffset - saveOutputOffset; 694 } 695 696 /** 697 * Calculates the output size for a returned byted array, or 698 * the size for the output array that will 699 * be passed through doFinalDecryption(.....). 700 * 701 * @param inputLength the input length, that will be base for the 702 * calculation. 703 * @return the size for a returned byted array, or 704 * the size for the output array that will 705 * be passed through doFinalDecryption(.....). 706 */ 707 public int getDoFinalDecryptionOutputSize(int inputLength) { 708 //Skip the rest if we divide with getBlockSize() 709 return ( 710 ( 711 this.unprocessedCipherTextBuffer.hasBytes() + inputLength 712 ) / getBlockSize() 713 ) * getBlockSize(); 714 } 715 716 /** Checks if the result from buffer bytes and 717 * a given inputLength is a multiple of the 718 * block size of the underlying mode object. 719 * @param inputLength the input length, that will be base for the 720 * verification. 721 * @return true if the result from buffer bytes and 722 * a given inputLength is a multiple of the 723 * block size of the underlying mode object, 724 * false otherwise. 725 */ 726 private boolean isCipherTextBufferAndInputLengthMultipleOfBlockSize( 727 int inputLength) { 728 return ( 729 this.unprocessedCipherTextBuffer.hasBytes() + inputLength 730 ) % getBlockSize() == 0; 731 } 732 733 /** 734 * Decrypts data in a single part operation, or finishes 735 * a multipart decryption. 736 * @param input padded cipherText that should be decrypted. 737 * @param inputOffset the offset in input where the input starts. 738 * @param inputLength the input length. 739 * @throws IllegalBlockSizeException if the final size of processed bytes 740 * not a multiple of block size. 741 * @return the unpadded and decrypted data. 742 */ 743 public byte[] doFinalDecryption(byte[] input, int inputOffset, 744 int inputLength) throws IllegalBlockSizeException { 745 //The next three if's are the same as the JCE does check, 746 //but these checks are not documented, so we do check again. 747 if (input == null && inputOffset == 0 && inputLength == 0) { 748 //At these point the JCE byte[] doFinal() was invoked. 749 } else { 750 751 if (input == null) { 752 throw new IllegalArgumentException("Bad Arguments."); 753 } 754 755 if (inputOffset < 0 || 756 inputLength < 0 || 757 input.length < (inputOffset+inputLength)) { 758 759 throw new IllegalArgumentException("Bad Arguments."); 760 } 761 } 762 763 if (isCipherTextBufferAndInputLengthMultipleOfBlockSize(inputLength) == false){ 764 throw new IllegalBlockSizeException("Input length not multiple of " 765 + getBlockSize() + " bytes."); 766 } 767 768 byte[] output = new byte[getDoFinalDecryptionOutputSize(inputLength)]; 769 int outputOffset =0; 770 771 //Process the whole input. 772 for (int i = inputOffset; i < inputOffset+inputLength; i++) { 773 774 //Add every single byte to our unprocessedCipherTextBuffer. 775 this.unprocessedCipherTextBuffer.add(input[i]); 776 777 //If our unprocessedCipherTextBuffer has enough bytes, process it 778 //and put the result into output. 779 if (this.unprocessedCipherTextBuffer.isFull()) { 780 781 //If one of the Exception, declared in the catch clause, was 782 //thrown, the cause is orginated here, so we catch it here. 783 try { 784 this.unprocessedCipherTextBuffer.fetch(this.tempBuffer, 0); 785 786 //Process our unprocessedCipherTextBuffer and add the number 787 //of new output bytes to outputOffset. 788 outputOffset += 789 this.mode.decrypt(this.tempBuffer, 0, output, outputOffset); 790 } catch (ShortBufferException cannothappen){ 791 throw new Error("Can not happen.", cannothappen); 792 } 793 } 794 } 795 796 //At these point we reset the mode Iv, to leave the Object in a valid 797 //state (for further use). 798 this.mode.resetToIv(); 799 800 //Return the result as byte array. 801 return output; 802 } 803 804 /** 805 * Decrypts data in a single part operation, or finishes 806 * a multipart decryption. 807 * 808 * @param input padded cipherText that should be decrypted. 809 * @param inputOffset the offset in input where the input starts. 810 * @param inputLength the input length. 811 * @param output the buffer for the unpadded and decrypted result. 812 * @param outputOffset the offset in output where the result is stored. 813 * @throws IllegalBlockSizeException if the final size of processed bytes 814 * not a multiple of block size. 815 * @throws ShortBufferException if the usable range in the output buffer is 816 * to less. This means that the usable range must at least 817 * getDoFinalDecryptionOutputSize(inputLength) bytes large. 818 * @throws IllegalArgumentException if <tt>input == null</tt>, 819 * <tt>inputOffset < 0</tt>, <tt>inputLength < 0</tt>, 820 * <tt>outputOffset < 0</tt> or <tt>input.length < 821 * inputOffset+inputLength</tt>. 822 * @return the number of bytes stored in output. 823 */ 824 public int doFinalDecryption(byte[] input, int inputOffset, int inputLength, 825 byte[] output, int outputOffset) 826 throws IllegalBlockSizeException, ShortBufferException { 827 //The next three if's are the same as the JCE does check, 828 //but these checks are not documented, so we do check again. 829 if (input == null && inputOffset == 0 && inputLength == 0) { 830 //At these point the JCE byte[] doFinal() was invoked. 831 } else { 832 833 if (input == null) { 834 throw new IllegalArgumentException("Bad Arguments."); 835 } 836 837 if (inputOffset < 0 || 838 inputLength < 0 || 839 input.length < (inputOffset+inputLength) ) { 840 841 throw new IllegalArgumentException("Bad Arguments."); 842 } 843 } 844 845 if (isCipherTextBufferAndInputLengthMultipleOfBlockSize(inputLength) == false) { 846 throw new IllegalBlockSizeException("Input length not multiple of " 847 + getBlockSize() + " bytes."); 848 } 849 850 int saveOutputOffset = outputOffset; 851 852 //Process the whole input. 853 for (int i = inputOffset; i < inputOffset+inputLength; i++){ 854 855 //Add every single byte to our unprocessedCipherTextBuffer. 856 this.unprocessedCipherTextBuffer.add(input[i]); 857 858 //If our unprocessedCipherTextBuffer has enough bytes, process it 859 //and put the result into output. 860 if (this.unprocessedCipherTextBuffer.isFull()){ 861 862 this.unprocessedCipherTextBuffer.fetch(this.tempBuffer, 0); 863 864 //Process our unprocessedCipherTextBuffer and add the number 865 //of new output bytes to outputOffset. 866 outputOffset += 867 this.mode.decrypt(this.tempBuffer, 0, output, outputOffset); 868 } 869 } 870 871 //At these point we reset the mode Iv, to leave the Object in a valid 872 //state (for further use). 873 this.mode.resetToIv(); 874 875 //Return the number of bytes stored in output. 876 return outputOffset-saveOutputOffset; 877 } 878 } 879
|
PaddingNoPadding |
|