annotate 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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
1 /**
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
2 * This file is part of the dcrypt project.
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
3 *
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
4 * Copyright: Copyright (C) dcrypt contributors 2008. All rights reserved.
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
5 * License: MIT
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
6 * Authors: Thomas Dixon
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
7 */
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
8
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
9 module dcrypt.crypto.ciphers.TEA;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
10
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
11 import dcrypt.misc.Util;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
12 import dcrypt.crypto.BlockCipher;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
13
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
14 /** Implementation of the TEA cipher designed by
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
15 David Wheeler and Roger Needham. */
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
16 class TEA : BlockCipher {
1
483e4467b5f6 Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents: 0
diff changeset
17 private {
483e4467b5f6 Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents: 0
diff changeset
18 const uint ROUNDS = 32,
483e4467b5f6 Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents: 0
diff changeset
19 KEY_SIZE = 16,
483e4467b5f6 Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents: 0
diff changeset
20 BLOCK_SIZE = 8,
483e4467b5f6 Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents: 0
diff changeset
21 DELTA = 0x9e3779b9,
483e4467b5f6 Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents: 0
diff changeset
22 DECRYPT_SUM = 0xc6ef3720;
483e4467b5f6 Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents: 0
diff changeset
23 uint sk0, sk1, sk2, sk3, sum;
483e4467b5f6 Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents: 0
diff changeset
24 }
0
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
25
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
26 void reset(){}
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
27
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
28 char[] name() {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
29 return "TEA";
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
30 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
31
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
32 uint blockSize() {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
33 return BLOCK_SIZE;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
34 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
35
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
36 void init(bool encrypt, CipherParameters params) {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
37 SymmetricKey keyParams = cast(SymmetricKey)params;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
38 if (!keyParams)
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
39 throw new InvalidParameterError(
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
40 name()~": Invalid parameter passed to init");
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.
Thomas Dixon <reikon@reikon.us>
parents: 12
diff changeset
41 _encrypt = encrypt;
0
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
42
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
43 if (keyParams.key.length != KEY_SIZE)
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
44 throw new InvalidKeyError(
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
45 name()~": Invalid key length (requires 16 bytes)");
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
46
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
47 sk0 = Util.ubytesToUintBig(keyParams.key, 0);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
48 sk1 = Util.ubytesToUintBig(keyParams.key, 4);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
49 sk2 = Util.ubytesToUintBig(keyParams.key, 8);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
50 sk3 = Util.ubytesToUintBig(keyParams.key, 12);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
51
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.
Thomas Dixon <reikon@reikon.us>
parents: 12
diff changeset
52 _initialized = true;
0
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
53 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
54
12
8c7f8fecdd75 Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents: 8
diff changeset
55 uint update(void[] input_, void[] output_) {
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.
Thomas Dixon <reikon@reikon.us>
parents: 12
diff changeset
56 if (!_initialized)
0
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
57 throw new NotInitializedError(name()~": Cipher not initialized");
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
58
12
8c7f8fecdd75 Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents: 8
diff changeset
59 ubyte[] input = cast(ubyte[]) input_,
8c7f8fecdd75 Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents: 8
diff changeset
60 output = cast(ubyte[]) output_;
0
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
61
12
8c7f8fecdd75 Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents: 8
diff changeset
62 if (input.length < BLOCK_SIZE)
0
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
63 throw new ShortBufferError(name()~": Input buffer too short");
12
8c7f8fecdd75 Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents: 8
diff changeset
64
8c7f8fecdd75 Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents: 8
diff changeset
65 if (output.length < BLOCK_SIZE)
8c7f8fecdd75 Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents: 8
diff changeset
66 throw new ShortBufferError(name()~": Output buffer too short");
0
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
67
8
23c62e28b3a4 Reworked symmetric cipher classes to have SymmetricCipher as their superclass, and follow the general interface of init(), process(), etc. Made sure everything still passed test vectors. Removed Cipher class. I'll worry about that shit when we support something other than symmetric ciphers.
Thomas Dixon <reikon@reikon.us>
parents: 6
diff changeset
68 uint v0 = Util.ubytesToUintBig(input, 0),
23c62e28b3a4 Reworked symmetric cipher classes to have SymmetricCipher as their superclass, and follow the general interface of init(), process(), etc. Made sure everything still passed test vectors. Removed Cipher class. I'll worry about that shit when we support something other than symmetric ciphers.
Thomas Dixon <reikon@reikon.us>
parents: 6
diff changeset
69 v1 = Util.ubytesToUintBig(input, 4);
0
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
70
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.
Thomas Dixon <reikon@reikon.us>
parents: 12
diff changeset
71 sum = _encrypt ? 0 : DECRYPT_SUM;
0
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
72 for (int i = 0; i < ROUNDS; i++) {
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.
Thomas Dixon <reikon@reikon.us>
parents: 12
diff changeset
73 if (_encrypt) {
0
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
74 sum += DELTA;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
75 v0 += ((v1 << 4) + sk0) ^ (v1 + sum) ^ ((v1 >> 5) + sk1);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
76 v1 += ((v0 << 4) + sk2) ^ (v0 + sum) ^ ((v0 >> 5) + sk3);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
77 } else {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
78 v1 -= ((v0 << 4) + sk2) ^ (v0 + sum) ^ ((v0 >> 5) + sk3);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
79 v0 -= ((v1 << 4) + sk0) ^ (v1 + sum) ^ ((v1 >> 5) + sk1);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
80 sum -= DELTA;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
81 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
82 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
83
8
23c62e28b3a4 Reworked symmetric cipher classes to have SymmetricCipher as their superclass, and follow the general interface of init(), process(), etc. Made sure everything still passed test vectors. Removed Cipher class. I'll worry about that shit when we support something other than symmetric ciphers.
Thomas Dixon <reikon@reikon.us>
parents: 6
diff changeset
84 Util.uintToUbytesBig(v0, output, 0);
23c62e28b3a4 Reworked symmetric cipher classes to have SymmetricCipher as their superclass, and follow the general interface of init(), process(), etc. Made sure everything still passed test vectors. Removed Cipher class. I'll worry about that shit when we support something other than symmetric ciphers.
Thomas Dixon <reikon@reikon.us>
parents: 6
diff changeset
85 Util.uintToUbytesBig(v1, output, 4);
0
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
86
12
8c7f8fecdd75 Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents: 8
diff changeset
87 return BLOCK_SIZE;
0
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
88 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
89
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
90 /** Some TEA test vectors. */
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
91 unittest {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
92 static const char[][] test_keys = [
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
93 "00000000000000000000000000000000",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
94 "00000000000000000000000000000000",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
95 "0123456712345678234567893456789a",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
96 "0123456712345678234567893456789a"
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
97 ];
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
98
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
99 static const char[][] test_plaintexts = [
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
100 "0000000000000000",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
101 "0102030405060708",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
102 "0000000000000000",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
103 "0102030405060708"
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
104 ];
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
105
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
106 static const char[][] test_ciphertexts = [
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
107 "41ea3a0a94baa940",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
108 "6a2f9cf3fccf3c55",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
109 "34e943b0900f5dcb",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
110 "773dc179878a81c0"
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
111 ];
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
112
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
113
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
114 TEA t = new TEA();
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
115 foreach (uint i, char[] test_key; test_keys) {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
116 ubyte[] buffer = new ubyte[t.blockSize];
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
117 char[] result;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
118 SymmetricKey key = new SymmetricKey(Util.hexToUbytes(test_key));
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
119
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
120 // Encryption
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
121 t.init(true, key);
12
8c7f8fecdd75 Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents: 8
diff changeset
122 t.update(Util.hexToUbytes(test_plaintexts[i]), buffer);
0
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
123 result = Util.ubytesToHex(buffer);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
124 assert(result == test_ciphertexts[i],
2
71aae178f89a Added copy() to hash functions. Modified some code style.
Thomas Dixon <reikon@reikon.us>
parents: 1
diff changeset
125 t.name~": ("~result~") != ("~test_ciphertexts[i]~")");
0
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
126
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
127 // Decryption
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
128 t.init(false, key);
12
8c7f8fecdd75 Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents: 8
diff changeset
129 t.update(Util.hexToUbytes(test_ciphertexts[i]), buffer);
0
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
130 result = Util.ubytesToHex(buffer);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
131 assert(result == test_plaintexts[i],
6
5cb17e09d685 Minor edits to the unittests of hash functions and ciphers. Added AES and test vectors.
Thomas Dixon <reikon@reikon.us>
parents: 2
diff changeset
132 t.name~": ("~result~") != ("~test_plaintexts[i]~")");
0
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
133 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
134 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
135 }