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