Mercurial > projects > dcrypt
view dcrypt/crypto/modes/CTR.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 | 8b5eaf3c2979 |
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; public 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 wrappedCipher; private ubyte[] iv, counter, counterOutput; private bool initialized = false; /** * Params: * cipher = Block cipher to wrap. */ this (BlockCipher cipher) { wrappedCipher = cipher; } /** Returns: The underlying cipher we are wrapping. */ BlockCipher cipher() { return wrappedCipher; } char[] name() { return wrappedCipher.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"); wrappedCipher.init(true, ivParams.parameters); iv = ivParams.iv[0..blockSize]; counter = new ubyte[blockSize]; counter[] = iv; counterOutput = new ubyte[blockSize]; initialized = true; } 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_; uint len = (counter.length > input.length) ? input.length : counter.length; if (len > output.length) throw new ShortBufferError(name()~": Output buffer too short"); // Encrypt the counter wrappedCipher.update(counter, counterOutput); // XOR output with plaintext to create ciphertext for (int i = 0; i < len; i++) counterOutput[i] ^= input[i]; // Increment the counter for (int i = counter.length-1; i >= 0; i--) if (++counter[i]) break; output[0..len] = counterOutput[0..len]; return len; } uint blockSize() { return wrappedCipher.blockSize; } void reset() { counter[] = iv; wrappedCipher.reset(); } }