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