Mercurial > projects > dcrypt
view dcrypt/crypto/ciphers/TEA.d @ 14:5ce3012f1def
Removed some redundancy in code. Added NotSupportedError, a base PRNG class and a class which creates a PRNG from a hash function. Changed the MAC class' finalization methods to digest and hexDigest instead of finish and hexFinish respectively. Also added a base Checksum class, crc32 and adler32 in dcrypt.misc as per request.
author | Thomas Dixon <reikon@reikon.us> |
---|---|
date | Tue, 18 Nov 2008 18:03:40 -0500 |
parents | 8c7f8fecdd75 |
children | 4589f8c5eb3c |
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.ciphers.TEA; import dcrypt.misc.Util; import dcrypt.crypto.BlockCipher; /** Implementation of the TEA cipher designed by David Wheeler and Roger Needham. */ class TEA : BlockCipher { private { const uint ROUNDS = 32, KEY_SIZE = 16, BLOCK_SIZE = 8, DELTA = 0x9e3779b9, DECRYPT_SUM = 0xc6ef3720; uint sk0, sk1, sk2, sk3, sum; } void reset(){} char[] name() { return "TEA"; } uint blockSize() { return BLOCK_SIZE; } void init(bool encrypt, CipherParameters params) { SymmetricKey keyParams = cast(SymmetricKey)params; if (!keyParams) throw new InvalidParameterError( name()~": Invalid parameter passed to init"); _encrypt = encrypt; if (keyParams.key.length != KEY_SIZE) throw new InvalidKeyError( name()~": Invalid key length (requires 16 bytes)"); sk0 = Util.ubytesToUintBig(keyParams.key, 0); sk1 = Util.ubytesToUintBig(keyParams.key, 4); sk2 = Util.ubytesToUintBig(keyParams.key, 8); sk3 = Util.ubytesToUintBig(keyParams.key, 12); _initialized = true; } uint update(void[] input_, void[] output_) { if (!_initialized) throw new NotInitializedError(name()~": Cipher not initialized"); ubyte[] input = cast(ubyte[]) input_, output = cast(ubyte[]) output_; if (input.length < BLOCK_SIZE) throw new ShortBufferError(name()~": Input buffer too short"); if (output.length < BLOCK_SIZE) throw new ShortBufferError(name()~": Output buffer too short"); uint v0 = Util.ubytesToUintBig(input, 0), v1 = Util.ubytesToUintBig(input, 4); sum = _encrypt ? 0 : DECRYPT_SUM; for (int i = 0; i < ROUNDS; i++) { if (_encrypt) { sum += DELTA; v0 += ((v1 << 4) + sk0) ^ (v1 + sum) ^ ((v1 >> 5) + sk1); v1 += ((v0 << 4) + sk2) ^ (v0 + sum) ^ ((v0 >> 5) + sk3); } else { v1 -= ((v0 << 4) + sk2) ^ (v0 + sum) ^ ((v0 >> 5) + sk3); v0 -= ((v1 << 4) + sk0) ^ (v1 + sum) ^ ((v1 >> 5) + sk1); sum -= DELTA; } } Util.uintToUbytesBig(v0, output, 0); Util.uintToUbytesBig(v1, output, 4); return BLOCK_SIZE; } /** Some TEA test vectors. */ unittest { static const char[][] test_keys = [ "00000000000000000000000000000000", "00000000000000000000000000000000", "0123456712345678234567893456789a", "0123456712345678234567893456789a" ]; static const char[][] test_plaintexts = [ "0000000000000000", "0102030405060708", "0000000000000000", "0102030405060708" ]; static const char[][] test_ciphertexts = [ "41ea3a0a94baa940", "6a2f9cf3fccf3c55", "34e943b0900f5dcb", "773dc179878a81c0" ]; TEA t = new TEA(); foreach (uint i, char[] test_key; test_keys) { ubyte[] buffer = new ubyte[t.blockSize]; char[] result; SymmetricKey key = new SymmetricKey(Util.hexToUbytes(test_key)); // Encryption t.init(true, key); t.update(Util.hexToUbytes(test_plaintexts[i]), buffer); result = Util.ubytesToHex(buffer); assert(result == test_ciphertexts[i], t.name~": ("~result~") != ("~test_ciphertexts[i]~")"); // Decryption t.init(false, key); t.update(Util.hexToUbytes(test_ciphertexts[i]), buffer); result = Util.ubytesToHex(buffer); assert(result == test_plaintexts[i], t.name~": ("~result~") != ("~test_plaintexts[i]~")"); } } }