01: package ch.ethz.ssh2.crypto.cipher;
02:
03: /**
04: * CBCMode.
05: *
06: * @author Christian Plattner, plattner@inf.ethz.ch
07: * @version $Id: CBCMode.java,v 1.2 2005/12/05 17:13:27 cplattne Exp $
08: */
09: public class CBCMode implements BlockCipher {
10: BlockCipher tc;
11: int blockSize;
12: boolean doEncrypt;
13:
14: byte[] cbc_vector;
15: byte[] tmp_vector;
16:
17: public void init(boolean forEncryption, byte[] key) {
18: }
19:
20: public CBCMode(BlockCipher tc, byte[] iv, boolean doEncrypt)
21: throws IllegalArgumentException {
22: this .tc = tc;
23: this .blockSize = tc.getBlockSize();
24: this .doEncrypt = doEncrypt;
25:
26: if (this .blockSize != iv.length)
27: throw new IllegalArgumentException("IV must be "
28: + blockSize + " bytes long! (currently "
29: + iv.length + ")");
30:
31: this .cbc_vector = new byte[blockSize];
32: this .tmp_vector = new byte[blockSize];
33: System.arraycopy(iv, 0, cbc_vector, 0, blockSize);
34: }
35:
36: public int getBlockSize() {
37: return blockSize;
38: }
39:
40: private void encryptBlock(byte[] src, int srcoff, byte[] dst,
41: int dstoff) {
42: for (int i = 0; i < blockSize; i++)
43: cbc_vector[i] ^= src[srcoff + i];
44:
45: tc.transformBlock(cbc_vector, 0, dst, dstoff);
46:
47: System.arraycopy(dst, dstoff, cbc_vector, 0, blockSize);
48: }
49:
50: private void decryptBlock(byte[] src, int srcoff, byte[] dst,
51: int dstoff) {
52: /* Assume the worst, src and dst are overlapping... */
53:
54: System.arraycopy(src, srcoff, tmp_vector, 0, blockSize);
55:
56: tc.transformBlock(src, srcoff, dst, dstoff);
57:
58: for (int i = 0; i < blockSize; i++)
59: dst[dstoff + i] ^= cbc_vector[i];
60:
61: /* ...that is why we need a tmp buffer. */
62:
63: byte[] swap = cbc_vector;
64: cbc_vector = tmp_vector;
65: tmp_vector = swap;
66: }
67:
68: public void transformBlock(byte[] src, int srcoff, byte[] dst,
69: int dstoff) {
70: if (doEncrypt)
71: encryptBlock(src, srcoff, dst, dstoff);
72: else
73: decryptBlock(src, srcoff, dst, dstoff);
74: }
75: }
|