1   /* $RCSfile: OperationMode.java,v $
2    * $Revision: 1.5 $
3    * $Date: 2002/01/04 12:14:10 $
4    * $Author: uwe $
5    * $State: Exp $
6    *
7    * Created on August 3, 2001 3:49 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   * OperationMode Interface.
39   *
40   *
41   * <pre>
42   * We use the following class hierarchy:
43   * OperationMode(abstract)
44   *    |
45   *    +BlockCipherECBOperationMode
46   *    |
47   *    +BlockCipherCBCBlockOperationMode
48   *    |
49   *    +BlockCipherCFB[8,16,24,32,40,48,56,64]OperationMode(not yet implemented)
50   *    |
51   *    +BlockCipherOFB[8,16,24,32,40,48,56,64]OperationMode(not yet implemented)
52   *
53   * </pre>
54   *
55   *
56   *
57   * @author  <a href=mailto:uwe@cscc.de>Uwe G&uuml;nther</a>
58   * @version $Revision: 1.5 $
59   */
60  abstract class OperationMode {    
61  
62      /** 
63       * Return the algorithm specific block size in bytes. These block
64       * size will be processed if one encrypt or decrypt method runs.
65       * If you subclass these abstract class, you have to implement these 
66       * method.
67       *
68       * @return the algorithm specific block size in bytes.
69       */
70      public abstract int getBlockSize();
71      
72      /**
73       * The encryption operation.
74       *
75       * Use it to encrypt whole getBlockSize() long plaintext blocks camouflaged
76       * as byte[getBlockSize()] blocks. This operation handels only byte arrays
77       * with a length of getBlockSize() byte or greater. Has the input byte 
78       * array a length lesser than 8 an
79       * {@link javax.crypto.IllegalBlockSizeException} will be thrown.
80       *
81       * If (input.length > getBlockSize()) we use only the first getBlockSize()
82       * bytes for the input block.
83       *
84       * See the following example code:
85       *
86       * <PRE>      
87        public class Main{
88             public static void main(String[] args){
89       
90                 byte[] plain = {(byte)0x4e, (byte)0x6f,
91                                 (byte)0x77, (byte)0x20,
92                                 (byte)0x69, (byte)0x73,
93                                 (byte)0x20, (byte)0x74
94                                };
95       
96                 byte[] myKey = {(byte)0x01, (byte)0x23,
97                                 (byte)0x45, (byte)0x67,
98                                 (byte)0x89, (byte)0xab,
99                                 (byte)0xcd, (byte)0xef
100                              };
101      
102                BlockCipher myBlockCipher = null;
103                try{
104                    myBlockCipher = new DESCore1KeyBlockCipher(myKey);
105                } catch(IllegalBlockSizeException e){
106                    e.printStackTrace();
107                    System.exit(1);
108                }     
109      
110                OperationMode mode = 
111                    new BlockCipherECBOperationMode(myBlockCipher);                
112      
113                byte[] cipher = null;
114                try {
115                    cipher = mode.encrypt(plain);
116                } catch(IllegalBlockSizeException e) {
117                    e.printStackTrace();
118                    System.exit(1);
119                }
120      
121                //do something with the cipher[8] array...
122      
123                return;
124            }
125       }
126      *
127      *
128      * </PRE>
129      *
130      * @param input the getBlockSize() long data block that will be encrypted.
131      * @throws IllegalBlockSizeException will be thrown, if the
132      *          deliverd byte array has a length lesser than getBlockSize().
133      * @return a byte[getBlockSize()] array with the ciphertext.
134      */         
135     public byte[] encrypt(byte[] input) throws IllegalBlockSizeException {
136         //Throws IllegalBlockSizeException.
137         return encrypt(input, 0);    
138     }
139 
140     /** 
141      * The encryption operation.
142      *
143      * If (input.length-inputOffset > getBlockSize()) we use only the first 
144      * getBlockSize() bytes from the block.
145      *
146      * @param input the getBlockSize() data block that will be encrypted.
147      * @param inputOffset the offset in block where the input starts.
148      * @throws IllegalBlockSizeException will be thrown, if the
149      *         deliverd byte array has a length lesser than getBlockSize().
150      * @return a byte[getBlockSize()] array with the ciphertext.
151      */    
152     public byte[] encrypt(byte[] input, int inputOffset) 
153             throws IllegalBlockSizeException {        
154         byte[] returnValue = new byte[getBlockSize()];
155         
156         try{
157             //Throws IllegalBlockSizeException.
158             encrypt(input, inputOffset, returnValue, 0);
159         } catch (ShortBufferException cannothappen){
160             //These exception won't be thrown because we deliver the 
161             //byte array with the right lenth (ever getBlockSize() bytes long).
162             throw new Error("Can not happen.", cannothappen);
163         } 
164         
165         //Return the result as byte[getBlockSize()].        
166         return returnValue;    
167     }
168      
169     /**
170      * The abstract encryption operation. If you subclass these abstract class,
171      * you have to implement these method.
172      *
173      * If (input.length-inputOffset > getBlockSize()) we use only the first 
174      * getBlockSize() bytes from the block.
175      *
176      * @param input the getBlockSize() long data block that will be encrypted.
177      * @param inputOffset the offset in input where the input starts.
178      * @param output the buffer for the result.
179      * @param outputOffset the offset in output where the result is stored.
180      * @throws IllegalBlockSizeException will be thrown, if the
181      *          deliverd byte array has a length lesser than getBlockSize().
182      * @throws ShortBufferException will be thrown, if the
183      *          output buffer byte array has a length lesser than getBlockSize().
184      * @return the number of bytes stored in output.
185      */    
186     public abstract int encrypt(byte[] input,  int inputOffset, 
187                                 byte[] output, int outputOffset) 
188     throws IllegalBlockSizeException,
189            ShortBufferException;
190     
191     /** 
192      * The decryption operation.
193      *
194      * Use it to decrypt whole getBlockSize() long ciphertext blocks camouflaged
195      * as byte[getBlockSize()] blocks. This operation handels only byte arrays
196      * with a length of getBlockSize() bytes or greater. Has the input byte 
197      * array a length lesser than getBlockSize() an
198      * {@link javax.crypto.IllegalBlockSizeException} will be thrown.
199      *
200      * If (input.length > getBlockSize()) we use only the first getBlockSize() 
201      * bytes for the input block.
202      *
203      * See the following example code:
204      * <PRE>
205       
206      
207       import javax.crypto.IllegalBlockSizeException;
208      
209       public class Main{
210            public static void main(String[] args){
211      
212                byte[] cipher = {(byte)0x3f, (byte)0xa4,
213                                (byte)0x0e, (byte)0x8a,
214                                (byte)0x98, (byte)0x4d,
215                                (byte)0x48, (byte)0x15
216                              };
217      
218                byte[] myKey = {(byte)0x01, (byte)0x23,
219                                (byte)0x45, (byte)0x67,
220                                (byte)0x89, (byte)0xab,
221                                (byte)0xcd, (byte)0xef
222                              };
223      
224                BlockCipher myBlockCipher = null;
225                try {
226                    myBlockCipher = new DESCore1KeyBlockCipher(myKey);
227                } catch(IllegalBlockSizeException e) {
228                    e.printStackTrace();
229                    System.exit(1);
230                }
231      
232                OperationMode mode = 
233                    new BlockCipherECBOperationMode(myBlockCipher); 
234                
235                byte[] plain = null;
236                try{
237                    plain = mode.decrypt(cipher);
238                } catch(IllegalBlockSizeException e){
239                    e.printStackTrace();
240                    System.exit(1);
241               }
242      
243                //do something with the plain[8] array...
244      
245                return;
246            }
247       }
248      *
249      * </PRE>
250      * @param input the getBlockSize() long data block that will be decrypted.
251      * @throws IllegalBlockSizeException will be thrown, if the
252      *          deliverd byte array has a length lesser than getBlockSize().
253      * @return a byte[getBlockSize()] array with the plaintext.
254      */    
255     public byte[] decrypt(byte[] input) throws IllegalBlockSizeException {
256         //Throws IllegalBlockSizeException.
257         return decrypt(input, 0);    
258     }
259     
260     /** 
261      * The decryption operation.
262      *
263      * If (input.length-inputOffset > getBlockSize()) we use only the first 
264      * getBlockSize() bytes for the block.
265      *
266      * @param input the getBlockSize() long data block that will be decrypted.
267      * @param inputOffset the offset in block where the input starts.
268      * @throws IllegalBlockSizeException will be thrown, if the
269      *         deliverd byte array has a length lesser than getBlockSize().
270      * @return a byte[getBlockSize()] array with the ciphertext.
271      */    
272     public byte[] decrypt(byte[] input, int inputOffset) 
273             throws IllegalBlockSizeException {
274         byte[] returnValue = new byte[getBlockSize()];
275         
276         try{
277             //Throws IllegalBlockSizeException 
278             decrypt(input, inputOffset, returnValue, 0);
279         } catch (ShortBufferException cannothappen){
280             //These exception won't be thrown because we deliver the 
281             //byte array with the right lenth (ever getBlockSize() bytes long).
282             throw new Error("Can not happen.", cannothappen);
283         }
284         
285         //Return the result as byte[getBlockSize()].        
286         return returnValue;
287     }
288      
289     /** 
290      * The abstract decryption operation. If you subclass these abstract class,
291      * you have to implement these method.
292      *
293      * If (input.length-inputOffset > getBlockSize()) we use only the first 
294      * getBlockSize() bytes 
295      * for the block.
296      *
297      * @param input the getBlockSize() long data block that will be decrypted.
298      * @param inputOffset the offset in input where the input starts.
299      * @param output the buffer for the result.
300      * @param outputOffset the offset in output where the result is stored.
301      * @throws IllegalBlockSizeException will be thrown, if the
302      *          deliverd byte array has a length lesser than getBlockSize().
303      * @throws ShortBufferException will be thrown, if the
304      *          output buffer byte array has a length lesser than getBlockSize().
305      * @return the number of bytes stored in output.
306      */    
307     public abstract int decrypt(byte[] input,  int inputOffset, 
308             byte[] output, int outputOffset) 
309             throws IllegalBlockSizeException, ShortBufferException;    
310     
311     /** 
312      * Set an initialization vector (iv) as a deep copy.
313      * The iv have to getBlockSize() bytes long.
314      *
315      * @param iv the initialization vector (iv).
316      * @throws IllegalBlockSizeException if the iv is smaller than 8 bytes. 
317      * If the longer than 8 bytes, only the first 8 bytes are used.
318      */
319     public abstract void setIv(byte[] iv) throws IllegalBlockSizeException;
320     
321     /**
322      * Return a deep copy of the internal byte[] array,
323      * which contains the initialization vector (iv),
324      * or null of the mode does not need an iv.
325      * Such as ECB.
326      *
327      * @return a deep copy of the internal byte[] array,
328      * which contains the initialization vector (iv),
329      * or null of the mode does not need an iv.
330      */    
331     public abstract byte[] getIv();
332     
333     /** Set chaning vector to the initial iv value. */
334     public abstract void resetToIv();
335 }
336