Mercurial > projects > dcrypt
diff dcrypt/crypto/modes/CBC.d @ 27:8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
author | Thomas Dixon <reikon@reikon.us> |
---|---|
date | Sat, 09 May 2009 23:29:20 -0400 |
parents | 176c933827a8 |
children | ad687db713a4 |
line wrap: on
line diff
--- a/dcrypt/crypto/modes/CBC.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/modes/CBC.d Sat May 09 23:29:20 2009 -0400 @@ -11,34 +11,41 @@ import dcrypt.crypto.BlockCipher; public import dcrypt.crypto.params.ParametersWithIV; -debug (UnitTest) { +debug (UnitTest) +{ import dcrypt.crypto.ciphers.XTEA; import dcrypt.misc.ByteConverter; } /** This class implements the cipher block chaining (CBC) block mode. */ -class CBC : BlockCipher { - private BlockCipher wrappedCipher; - private ubyte[] iv, - previousCiphertext, - cbcOutput; - private bool encrypt, - initialized; +class CBC : BlockCipher +{ + private + { + BlockCipher wrappedCipher; + + ubyte[] iv, + previousBlock, + currentBlock; + } /** * Params: * cipher = Block cipher to wrap. */ - this (BlockCipher cipher) { + this (BlockCipher cipher) + { wrappedCipher = cipher; } /** Returns: The underlying cipher we are wrapping. */ - BlockCipher cipher() { + BlockCipher cipher() + { return wrappedCipher; } - char[] name() { + char[] name() + { return wrappedCipher.name~"/CBC"; } @@ -46,7 +53,8 @@ * Throws: dcrypt.crypto.errors.InvalidParameterError if params aren't * an instance of dcrypt.crypto.params.ParametersWithIV. */ - void init(bool encrypt, CipherParameters params) { + void init(bool encrypt, CipherParameters params) + { ParametersWithIV ivParams = cast(ParametersWithIV)params; if (!ivParams) @@ -56,21 +64,23 @@ throw new InvalidParameterError( name()~": IV must be same length as cipher block size"); - this.encrypt = encrypt; - wrappedCipher.init(encrypt, ivParams.parameters); + _encrypt = encrypt; + + wrappedCipher.init(_encrypt, ivParams.parameters); iv = ivParams.iv[0..blockSize]; - previousCiphertext = new ubyte[blockSize]; - previousCiphertext[] = iv; // C_0 = IV - cbcOutput = new ubyte[blockSize]; // Output buffer for E_k/D_k(...) - initialized = true; + currentBlock = new ubyte[blockSize]; + previousBlock = new ubyte[blockSize]; + previousBlock[] = iv; // C_0 = IV + + _initialized = true; } - uint update(void[] input_, void[] output_) { - if (!initialized) - throw new NotInitializedError( - name()~": Block mode not initialized"); + uint update(void[] input_, void[] output_) + { + if (!_initialized) + throw new NotInitializedError(name()~": Block mode not initialized"); ubyte[] input = cast(ubyte[]) input_, output = cast(ubyte[]) output_; @@ -81,49 +91,53 @@ if (output.length < blockSize) throw new ShortBufferError(name()~": Output buffer too short"); - if (encrypt) { + if (_encrypt) + { // P_i XOR C_i-1 for (int i = 0; i < blockSize; i++) - previousCiphertext[i] ^= input[i]; + previousBlock[i] ^= input[i]; - // E_k(P_i XOR C_i-1) - wrappedCipher.update(previousCiphertext, cbcOutput); - - // Store C_i for next block - previousCiphertext[] = cbcOutput; + // E_k(P_i XOR C_i-1) and store C_i for the next block + wrappedCipher.update(previousBlock, previousBlock); // C_i = E_k(P_i XOR C_i-1) - output[0..blockSize] = cbcOutput; - } else { - // Temporarily store C_i - ubyte[] t = input[0..blockSize]; + output[0..blockSize] = previousBlock; + } + else + { + // Local reference to C_i + ubyte[] temp = input[0..blockSize]; // D_k(C_i) - wrappedCipher.update(t, cbcOutput); + wrappedCipher.update(temp, currentBlock); // P_i = D_k(C_i) XOR C_i-1 for (int i = 0; i < blockSize; i++) - output[i] = (cbcOutput[i] ^ previousCiphertext[i]); + output[i] = (currentBlock[i] ^ previousBlock[i]); // Store C_i for next block - previousCiphertext[] = t; + previousBlock[] = temp; } return blockSize; } - uint blockSize() { + uint blockSize() + { return wrappedCipher.blockSize; } - void reset() { - previousCiphertext[] = iv; + void reset() + { + previousBlock[] = iv; wrappedCipher.reset(); } /** Test vectors for CBC mode. Assumes XTEA passes test vectors. */ - debug (UnitTest) { - unittest { + debug (UnitTest) + { + unittest + { static const char[][] test_keys = [ "00000000000000000000000000000000", "00000000000000000000000000000000", @@ -152,27 +166,27 @@ "f26fa5a0b6b63ba0f7ebf2f8735f85e3" ]; - XTEA x = new XTEA(); - CBC c = new CBC(x); - ubyte[] iv = new ubyte[x.blockSize], // Initialized to 0 + CBC c = new CBC(new XTEA); + ubyte[] iv = new ubyte[c.blockSize], // Initialized to 0 buffer = new ubyte[32]; char[] result; - for (int i = 0; i < test_keys.length; i++) { + for (int i = 0; i < test_keys.length; i++) + { SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_keys[i])); ParametersWithIV params = new ParametersWithIV(key, iv); // Encryption c.init(true, params); - for (int j = 0; j < 32; j+=x.blockSize) - c.update(ByteConverter.hexDecode(test_plaintexts[i])[j..j+x.blockSize], buffer[j..j+x.blockSize]); + for (int j = 0; j < 32; j+=c.blockSize) + c.update(ByteConverter.hexDecode(test_plaintexts[i])[j..j+c.blockSize], buffer[j..j+c.blockSize]); result = ByteConverter.hexEncode(buffer); assert(result == test_ciphertexts[i], c.name()~": ("~result~") != ("~test_ciphertexts[i]~")"); // Decryption c.init(false, params); - for (int j = 0; j < 32; j+=x.blockSize) - c.update(ByteConverter.hexDecode(test_ciphertexts[i])[j..j+x.blockSize], buffer[j..j+x.blockSize]); + for (int j = 0; j < 32; j+=c.blockSize) + c.update(ByteConverter.hexDecode(test_ciphertexts[i])[j..j+c.blockSize], buffer[j..j+c.blockSize]); result = ByteConverter.hexEncode(buffer); assert(result == test_plaintexts[i], c.name()~": ("~result~") != ("~test_plaintexts[i]~")");