Mercurial > projects > dcrypt
diff dcrypt/crypto/modes/CTR.d @ 0:0e08791a1418
Initial import.
author | Thomas Dixon <reikon@reikon.us> |
---|---|
date | Sun, 10 Aug 2008 14:20:17 -0400 |
parents | |
children | 23c62e28b3a4 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcrypt/crypto/modes/CTR.d Sun Aug 10 14:20:17 2008 -0400 @@ -0,0 +1,95 @@ +/** + * This file is part of the dcrypt project. + * + * Copyright: Copyright (C) dcrypt contributors 2008. All rights reserved. + * License: MIT + * Authors: Thomas Dixon + */ + +module dcrypt.crypto.modes.CTR; + +import dcrypt.crypto.BlockCipher; +import dcrypt.crypto.params.ParametersWithIV; + + +/** This class implements the counter (CTR/SIC/ICM) block mode, + treating the counter as a big endian integer. */ +class CTR : BlockCipher { + private BlockCipher m_cipher; + private ubyte[] iv, + counter, + counterOutput; + private bool initialized = false; + + /** + * Params: + * cipher = Block cipher to wrap. + */ + this (BlockCipher cipher) { + m_cipher = cipher; + } + + /** Returns: The underlying cipher we are wrapping. */ + BlockCipher cipher() { + return m_cipher; + } + + char[] name() { + return m_cipher.name~"/CTR"; + } + + /** + * Throws: dcrypt.crypto.errors.InvalidParameterError if params aren't + * an instance of dcrypt.crypto.params.ParametersWithIV. + */ + void init(bool encrypt, CipherParameters params) { + ParametersWithIV ivParams = cast(ParametersWithIV)params; + + if (!ivParams) + throw new InvalidParameterError( + name()~": Block mode requires IV (use ParametersWithIV)"); + if (ivParams.iv.length != blockSize) + throw new InvalidParameterError( + name()~": IV must be same length as cipher block size"); + + m_cipher.init(true, ivParams.parameters); + + iv = ivParams.iv[0..blockSize]; + counter = new ubyte[blockSize]; + counter[] = iv; + counterOutput = new ubyte[blockSize]; + + initialized = true; + } + + uint processBlock(void[] input_, uint inOff, void[] output_, uint outOff) { + if (!initialized) + throw new NotInitializedError( + name()~": Block mode not initialized"); + + ubyte[] input = cast(ubyte[]) input_; + ubyte[] output = cast(ubyte[]) output_; + + // Encrypt the counter + m_cipher.processBlock(counter, 0, counterOutput, 0); + + // XOR output with plaintext to create ciphertext + for (int i = 0; i < counter.length; i++) + output[outOff++] = (counterOutput[i] ^ input[inOff++]); + + // Increment the counter + for (int i = counter.length-1; i >= 0; i--) + if (++counter[i]) break; + + return counter.length; + } + + uint blockSize() { + return m_cipher.blockSize; + } + + void reset() { + counter[] = iv; + m_cipher.reset(); + } +}