KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > de > schlichtherle > crypto > modes > SICSeekableBlockCipher


1 /*
2  * SICSeekableBlockCipher.java
3  *
4  * Created on 3. Oktober 2005, 15:40
5  */

6 /*
7  * Copyright 2005 Schlichtherle IT Services
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */

21
22 package de.schlichtherle.crypto.modes;
23
24 import de.schlichtherle.crypto.SeekableBlockCipher;
25
26 import org.bouncycastle.crypto.BlockCipher;
27 import org.bouncycastle.crypto.CipherParameters;
28 import org.bouncycastle.crypto.DataLengthException;
29 import org.bouncycastle.crypto.params.ParametersWithIV;
30
31 /**
32  * Implements the Segmented Integer Counter (SIC) mode on top of a simple
33  * blockCounter cipher. This mode is also known as CTR mode.
34  * This code is based on bouncy castle's <tt>SICBlockCipher</tt> class,
35  * but also allows random access to a blockCounter.
36  *
37  * @author The Legion of the Bouncy Castle (majority of the code)
38  * @author Christian Schlichtherle (optimizations and extension to support seeking)
39  */

40 public class SICSeekableBlockCipher implements SeekableBlockCipher {
41
42     private final BlockCipher cipher;
43     private final int blockSize;
44     private final byte[] IV;
45     private final byte[] counter;
46     private long blockCounter; // the blockCounter counter
47
private final byte[] counterOut;
48
49     /**
50      * Basic constructor.
51      *
52      * @param c the blockCounter cipher to be used.
53      */

54     public SICSeekableBlockCipher(BlockCipher c) {
55         this.cipher = c;
56         this.blockSize = cipher.getBlockSize();
57         this.IV = new byte[blockSize];
58         this.counter = new byte[blockSize];
59         this.counterOut = new byte[blockSize];
60     }
61
62     /**
63      * return the underlying blockCounter cipher that we are wrapping.
64      *
65      * @return the underlying blockCounter cipher that we are wrapping.
66      */

67     public BlockCipher getUnderlyingCipher() {
68         return cipher;
69     }
70
71     public void init(boolean forEncryption, CipherParameters params)
72     throws IllegalArgumentException JavaDoc {
73         if (params instanceof ParametersWithIV) {
74           ParametersWithIV ivParams = (ParametersWithIV) params;
75           byte[] iv = ivParams.getIV();
76           System.arraycopy(iv, 0, IV, 0, IV.length);
77
78           reset();
79           cipher.init(true, ivParams.getParameters());
80         }
81     }
82
83     public String JavaDoc getAlgorithmName() {
84         // Must add "/SIC" in order to make BufferedBlockCipher work correctly.
85
return cipher.getAlgorithmName() + "/SIC";
86     }
87
88     public int getBlockSize() {
89         assert blockSize == cipher.getBlockSize();
90         return blockSize;
91     }
92
93     public int processBlock(
94             final byte[] in,
95             final int inOff,
96             final byte[] out,
97             final int outOff)
98     throws DataLengthException, IllegalStateException JavaDoc {
99         updateCounter();
100         cipher.processBlock(counter, 0, counterOut, 0);
101
102         // XOR the counterOut with the plaintext producing the cipher text.
103
for (int i = blockSize; --i >= 0; ) {
104           out[outOff + i] = (byte)(counterOut[i] ^ in[inOff + i]);
105         }
106
107         blockCounter++;
108
109         return blockSize;
110     }
111
112     private final void updateCounter() {
113         long block = this.blockCounter;
114         for (int i = blockSize; --i >= 0; ) {
115             block += IV[i] & 0xff;
116             counter[i] = (byte) block;
117             block >>>= 8;
118         }
119     }
120
121     public void setBlockCounter(long block) {
122         blockCounter = block;
123     }
124
125     public long getBlockCounter() {
126         return blockCounter;
127     }
128
129     public void reset() {
130         // Effectively the same as setBlockCounter(0).
131
//System.arraycopy(IV, 0, counter, 0, blockSize);
132
blockCounter = 0;
133         
134         cipher.reset();
135     }
136 }
Popular Tags