comparison dcrypt/crypto/modes/CBC.d @ 23:4589f8c5eb3c

Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
author Thomas Dixon <reikon@reikon.us>
date Sat, 14 Feb 2009 19:58:20 -0500
parents 8c7f8fecdd75
children 176c933827a8
comparison
equal deleted inserted replaced
22:74303a717032 23:4589f8c5eb3c
11 import dcrypt.crypto.BlockCipher; 11 import dcrypt.crypto.BlockCipher;
12 public import dcrypt.crypto.params.ParametersWithIV; 12 public import dcrypt.crypto.params.ParametersWithIV;
13 13
14 version (UnitTest) { 14 version (UnitTest) {
15 import dcrypt.crypto.ciphers.XTEA; 15 import dcrypt.crypto.ciphers.XTEA;
16 import dcrypt.misc.Util; 16 import dcrypt.misc.ByteConverter;
17 } 17 }
18 18
19 /** This class implements the cipher block chaining (CBC) block mode. */ 19 /** This class implements the cipher block chaining (CBC) block mode. */
20 class CBC : BlockCipher { 20 class CBC : BlockCipher {
21 private BlockCipher m_cipher; 21 private BlockCipher wrappedCipher;
22 private ubyte[] iv, 22 private ubyte[] iv,
23 previousCiphertext, 23 previousCiphertext,
24 cbcOutput; 24 cbcOutput;
25 private bool encrypt, 25 private bool encrypt,
26 initialized; 26 initialized;
28 /** 28 /**
29 * Params: 29 * Params:
30 * cipher = Block cipher to wrap. 30 * cipher = Block cipher to wrap.
31 */ 31 */
32 this (BlockCipher cipher) { 32 this (BlockCipher cipher) {
33 m_cipher = cipher; 33 wrappedCipher = cipher;
34 } 34 }
35 35
36 /** Returns: The underlying cipher we are wrapping. */ 36 /** Returns: The underlying cipher we are wrapping. */
37 BlockCipher cipher() { 37 BlockCipher cipher() {
38 return m_cipher; 38 return wrappedCipher;
39 } 39 }
40 40
41 char[] name() { 41 char[] name() {
42 return m_cipher.name~"/CBC"; 42 return wrappedCipher.name~"/CBC";
43 } 43 }
44 44
45 /** 45 /**
46 * Throws: dcrypt.crypto.errors.InvalidParameterError if params aren't 46 * Throws: dcrypt.crypto.errors.InvalidParameterError if params aren't
47 * an instance of dcrypt.crypto.params.ParametersWithIV. 47 * an instance of dcrypt.crypto.params.ParametersWithIV.
48 */ 48 */
49 void init(bool encrypt, CipherParameters params) { 49 void init(bool encrypt, CipherParameters params) {
50 ParametersWithIV ivParams = cast(ParametersWithIV)params; 50 ParametersWithIV ivParams = cast(ParametersWithIV)params;
51 51
52 if (!ivParams) 52 if (!ivParams)
55 if (ivParams.iv.length != blockSize) 55 if (ivParams.iv.length != blockSize)
56 throw new InvalidParameterError( 56 throw new InvalidParameterError(
57 name()~": IV must be same length as cipher block size"); 57 name()~": IV must be same length as cipher block size");
58 58
59 this.encrypt = encrypt; 59 this.encrypt = encrypt;
60 m_cipher.init(encrypt, ivParams.parameters); 60 wrappedCipher.init(encrypt, ivParams.parameters);
61 61
62 iv = ivParams.iv[0..blockSize]; 62 iv = ivParams.iv[0..blockSize];
63 previousCiphertext = new ubyte[blockSize]; 63 previousCiphertext = new ubyte[blockSize];
64 previousCiphertext[] = iv; // C_0 = IV 64 previousCiphertext[] = iv; // C_0 = IV
65 cbcOutput = new ubyte[blockSize]; // Output buffer for E_k/D_k(...) 65 cbcOutput = new ubyte[blockSize]; // Output buffer for E_k/D_k(...)
85 // P_i XOR C_i-1 85 // P_i XOR C_i-1
86 for (int i = 0; i < blockSize; i++) 86 for (int i = 0; i < blockSize; i++)
87 previousCiphertext[i] ^= input[i]; 87 previousCiphertext[i] ^= input[i];
88 88
89 // E_k(P_i XOR C_i-1) 89 // E_k(P_i XOR C_i-1)
90 m_cipher.update(previousCiphertext, cbcOutput); 90 wrappedCipher.update(previousCiphertext, cbcOutput);
91 91
92 // Store C_i for next block 92 // Store C_i for next block
93 previousCiphertext[] = cbcOutput; 93 previousCiphertext[] = cbcOutput;
94 94
95 // C_i = E_k(P_i XOR C_i-1) 95 // C_i = E_k(P_i XOR C_i-1)
97 } else { 97 } else {
98 // Temporarily store C_i 98 // Temporarily store C_i
99 ubyte[] t = input[0..blockSize]; 99 ubyte[] t = input[0..blockSize];
100 100
101 // D_k(C_i) 101 // D_k(C_i)
102 m_cipher.update(t, cbcOutput); 102 wrappedCipher.update(t, cbcOutput);
103 103
104 // P_i = D_k(C_i) XOR C_i-1 104 // P_i = D_k(C_i) XOR C_i-1
105 for (int i = 0; i < blockSize; i++) 105 for (int i = 0; i < blockSize; i++)
106 output[i] = (cbcOutput[i] ^ previousCiphertext[i]); 106 output[i] = (cbcOutput[i] ^ previousCiphertext[i]);
107 107
111 111
112 return blockSize; 112 return blockSize;
113 } 113 }
114 114
115 uint blockSize() { 115 uint blockSize() {
116 return m_cipher.blockSize; 116 return wrappedCipher.blockSize;
117 } 117 }
118 118
119 void reset() { 119 void reset() {
120 previousCiphertext[] = iv; 120 previousCiphertext[] = iv;
121 m_cipher.reset(); 121 wrappedCipher.reset();
122 } 122 }
123 123
124 /** Test vectors for CBC mode. Assumes XTEA passes test vectors. */ 124 /** Test vectors for CBC mode. Assumes XTEA passes test vectors. */
125 version (UnitTest) { 125 version (UnitTest) {
126 unittest { 126 unittest {
156 CBC c = new CBC(x); 156 CBC c = new CBC(x);
157 ubyte[] iv = new ubyte[x.blockSize], // Initialized to 0 157 ubyte[] iv = new ubyte[x.blockSize], // Initialized to 0
158 buffer = new ubyte[32]; 158 buffer = new ubyte[32];
159 char[] result; 159 char[] result;
160 for (int i = 0; i < test_keys.length; i++) { 160 for (int i = 0; i < test_keys.length; i++) {
161 SymmetricKey key = new SymmetricKey(Util.hexToUbytes(test_keys[i])); 161 SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_keys[i]));
162 ParametersWithIV params = new ParametersWithIV(key, iv); 162 ParametersWithIV params = new ParametersWithIV(key, iv);
163 163
164 // Encryption 164 // Encryption
165 c.init(true, params); 165 c.init(true, params);
166 for (int j = 0; j < 32; j+=x.blockSize) 166 for (int j = 0; j < 32; j+=x.blockSize)
167 c.update(Util.hexToUbytes(test_plaintexts[i])[j..j+x.blockSize], buffer[j..j+x.blockSize]); 167 c.update(ByteConverter.hexDecode(test_plaintexts[i])[j..j+x.blockSize], buffer[j..j+x.blockSize]);
168 result = Util.ubytesToHex(buffer); 168 result = ByteConverter.hexEncode(buffer);
169 assert(result == test_ciphertexts[i], 169 assert(result == test_ciphertexts[i],
170 c.name()~": ("~result~") != ("~test_ciphertexts[i]~")"); 170 c.name()~": ("~result~") != ("~test_ciphertexts[i]~")");
171 171
172 // Decryption 172 // Decryption
173 c.init(false, params); 173 c.init(false, params);
174 for (int j = 0; j < 32; j+=x.blockSize) 174 for (int j = 0; j < 32; j+=x.blockSize)
175 c.update(Util.hexToUbytes(test_ciphertexts[i])[j..j+x.blockSize], buffer[j..j+x.blockSize]); 175 c.update(ByteConverter.hexDecode(test_ciphertexts[i])[j..j+x.blockSize], buffer[j..j+x.blockSize]);
176 result = Util.ubytesToHex(buffer); 176 result = ByteConverter.hexEncode(buffer);
177 assert(result == test_plaintexts[i], 177 assert(result == test_plaintexts[i],
178 c.name()~": ("~result~") != ("~test_plaintexts[i]~")"); 178 c.name()~": ("~result~") != ("~test_plaintexts[i]~")");
179 } 179 }
180 } 180 }
181 } 181 }