Mercurial > projects > dcrypt
view 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 source
/** * 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(); } }