|
OperationModeCBC |
|
1 /* $RCSfile: OperationModeCBC.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 16, 2001 11:36 AM
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 import de.cscc.crypto.util.ByteUtil;
38
39 /**
40 * OperationModeCBC Class.
41 *
42 * @author <a href=mailto:uwe@cscc.de>Uwe Günther</a>
43 * @version $Revision: 1.11 $
44 */
45 class OperationModeCBC extends OperationMode {
46
47 /**
48 * A BlockCipher object that will be used for this OperationMode
49 * algorithm.
50 */
51 private BlockCipher cipher;
52
53 /**
54 * The initialization vector where we will start the
55 * cipher block chaining.
56 */
57 private byte[] iv;
58
59 /** The current valid chaining vector that will be used. */
60 private byte[] chainingVector;
61
62 /** Don't create a new OperationModeCBC with the default constructor. */
63 private OperationModeCBC() {}
64
65 /**
66 * Creates new OperationModeCBC with a BlockCipher.
67 * Default iv is 0x000000 ... 000 with length == getBlockSize().
68 *
69 * @param cipher the cipher to wrap.
70 */
71 public OperationModeCBC(BlockCipher cipher) {
72 this.cipher = cipher;
73
74 //set default iv
75 this.iv = new byte[getBlockSize()];
76 this.chainingVector = new byte[getBlockSize()];
77 }
78
79 /**
80 * Returns a string representation of the object.
81 *
82 * @return a string representation of the object.
83 */
84 public String toString() {
85 String returnValue = "";
86 returnValue += "Cipher: [" + this.cipher + "] ";
87 returnValue += "IV: [" + ByteUtil.toHex(this.iv) + "] ";
88 returnValue += "Chaining Vector: [null] ";
89 returnValue += "Chaining Vector: [" +
90 ByteUtil.toHex(this.chainingVector) + "]";
91 return returnValue;
92 }
93
94 /**
95 * Set an initialization vector (iv) as a deep copy.
96 * The iv have to getBlockSize() bytes long.
97 *
98 * @param iv the initialization vector (iv).
99 * @throws IllegalBlockSizeException if the iv is smaller than 8 bytes.
100 * If the longer than 8 bytes, only the first 8 bytes are used.
101 */
102 public void setIv(byte[] iv) throws IllegalBlockSizeException {
103 if (iv.length < getBlockSize()){
104 throw new IllegalBlockSizeException(
105 "Initialization Vector is " + iv.length +
106 " bytes long, but it should be " +
107 getBlockSize() + ".");
108 }
109
110 System.arraycopy(iv, 0, this.iv, 0, getBlockSize());
111
112 //If we set the Iv we will also set the chaining vector to the Iv,
113 //because we start aevery time with the Iv, if the Iv is new set.
114 setChainingVector(this.iv, 0);
115 }
116
117 /**
118 * Returns a deep copy of the internal byte[] array,
119 * which contains the initialization vector (iv),
120 * or null of the mode does not need an iv.
121 * Such as ECB.
122 *
123 * @return a deep copy of the internal byte[] array,
124 * which contains the initialization vector (iv),
125 * or null of the mode does not need an iv.
126 */
127 public byte[] getIv() {
128 /*byte[] returnValue = new byte[getBlockSize()];
129 System.arraycopy(this.iv, 0, returnValue, 0, getBlockSize());
130 return returnValue;*/
131 return (byte[]) this.iv.clone();
132 }
133
134 /** Set chaning vector to the initial iv value. */
135 public void resetToIv() {
136 try {
137 setChainingVector(this.iv, 0);
138 } catch (IllegalBlockSizeException cannothappen) {
139 //Will never be thrown because this.iv.length == getBlockSize().
140 throw new Error("Can not happen.", cannothappen);
141 }
142 }
143
144 /**
145 * Set the current valid chaining vector from a
146 * byte[offset+8] array.
147 * @param input the input buffer.
148 * @param offset the offset in input where the input starts.
149 * @throws IllegalBlockSizeException will be thrown, if the
150 * deliverd byte array has a length lesser than 8.
151 */
152 private void setChainingVector(byte[] input, int offset)
153 throws IllegalBlockSizeException {
154 if (input.length-offset < getBlockSize()){
155 throw new IllegalBlockSizeException(
156 "Initialization Vector is " + (input.length-offset) +
157 " bytes long, but it should be " + getBlockSize() + ".");
158 }
159
160 System.arraycopy(input, offset,
161 this.chainingVector, 0,
162 getBlockSize());
163 }
164
165 /**
166 * Returns the algorithm specific block size in bytes. These block
167 * size will be processed if one encrypt or decrypt method runs.
168 * If you subclass these abstract class, you have to implement these
169 * method.
170 *
171 * @return the algorithm specific block size in bytes.
172 */
173 public int getBlockSize() {
174 return this.cipher.getBlockSize();
175 }
176
177 /**
178 * The encryption operation.
179 *
180 * If (input.length-inputOffset > 8) we use only the first 8 bytes
181 * for the block.
182 *
183 * @param input the 64 bit data block that will be encrypted.
184 * @param inputOffset the offset in input where the input starts.
185 * @param output the buffer for the result.
186 * @param outputOffset the offset in output where the result is stored.
187 * @throws IllegalBlockSizeException will be thrown, if the
188 * deliverd byte array has a length lesser than 8.
189 * @throws ShortBufferException will be thrown, if the
190 * output buffer byte array has a length lesser than 8.
191 * @return the number of bytes stored in output.
192 */
193 public int encrypt(byte[] input, int inputOffset,
194 byte[] output, int outputOffset)
195 throws IllegalBlockSizeException, ShortBufferException {
196
197 // we check only the input buffer, because the output buffer
198 // will be checked in this.cipher.encrypt(...)
199 if (input.length-inputOffset < getBlockSize()){
200 throw new IllegalBlockSizeException(
201 "The input block range is " + (input.length-inputOffset) +
202 " bytes long, but it should be " + getBlockSize() +
203 " or longer.");
204 }
205
206 //xor chaning vector with input block
207 for (int i =0; i < getBlockSize(); i++){
208 this.chainingVector[i] ^= input[inputOffset+i];
209 }
210
211 //Xor the chaining Vector to input block.
212 //Throws IllegalBlockSizeException and/or ShortBufferException
213 int returnValue = this.cipher.encrypt(this.chainingVector, 0,
214 output, outputOffset);
215
216 //Set the new encryptd cipher text block as new chaining vector
217 //for the next encrypt() invokation.
218 setChainingVector(output, outputOffset);
219
220 return returnValue;
221 }
222
223 /**
224 * The DES decryption operation.
225 *
226 * If (input.length-inputOffset > 8) we use only the first 8 bytes
227 * for the block.
228 *
229 * @param input the 64 bit data block that will be decrypted.
230 * @param inputOffset the offset in input where the input starts.
231 * @param output the buffer for the result.
232 * @param outputOffset the offset in output where the result is stored.
233 * @throws IllegalBlockSizeException will be thrown, if the
234 * deliverd byte array has a length lesser than getBlockSize().
235 * @throws ShortBufferException will be thrown, if the
236 * output buffer byte array has a length lesser than getBlockSize().
237 * @return the number of bytes stored in output.
238 */
239 public int decrypt(byte[] input, int inputOffset,
240 byte[] output, int outputOffset)
241 throws IllegalBlockSizeException, ShortBufferException {
242 //Decrypt the cipher text block.
243 int returnValue = this.cipher.decrypt(input, inputOffset,
244 output, outputOffset);
245
246 //Xor the plaintext block with the chaining vector.
247 //Throws IllegalBlockSizeException and/or ShortBufferException
248 for (int i = 0; i < getBlockSize(); i++){
249 output[outputOffset+i] ^= this.chainingVector[i];
250 }
251
252 //Set the chaining vector for the next decrypt round
253 //to the encrypted input for this decrypt round.
254 setChainingVector(input, inputOffset);
255
256 //Returns the block lentgh in byte, usually 8 byte.
257 return returnValue;
258 }
259 }
260
|
OperationModeCBC |
|