Mercurial > projects > dcrypt
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 |
rev | line source |
---|---|
0 | 1 /** |
2 * This file is part of the dcrypt project. | |
3 * | |
4 * Copyright: Copyright (C) dcrypt contributors 2008. All rights reserved. | |
5 * License: MIT | |
6 * Authors: Thomas Dixon | |
7 */ | |
8 | |
9 module dcrypt.crypto.ciphers.TEA; | |
10 | |
11 import dcrypt.misc.Util; | |
12 import dcrypt.crypto.BlockCipher; | |
13 | |
14 /** Implementation of the TEA cipher designed by | |
15 David Wheeler and Roger Needham. */ | |
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 | 25 |
26 void reset(){} | |
27 | |
28 char[] name() { | |
29 return "TEA"; | |
30 } | |
31 | |
32 uint blockSize() { | |
33 return BLOCK_SIZE; | |
34 } | |
35 | |
36 void init(bool encrypt, CipherParameters params) { | |
37 SymmetricKey keyParams = cast(SymmetricKey)params; | |
38 if (!keyParams) | |
39 throw new InvalidParameterError( | |
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 | 42 |
43 if (keyParams.key.length != KEY_SIZE) | |
44 throw new InvalidKeyError( | |
45 name()~": Invalid key length (requires 16 bytes)"); | |
46 | |
47 sk0 = Util.ubytesToUintBig(keyParams.key, 0); | |
48 sk1 = Util.ubytesToUintBig(keyParams.key, 4); | |
49 sk2 = Util.ubytesToUintBig(keyParams.key, 8); | |
50 sk3 = Util.ubytesToUintBig(keyParams.key, 12); | |
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 | 53 } |
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 | 57 throw new NotInitializedError(name()~": Cipher not initialized"); |
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 | 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 | 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 | 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 | 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 | 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 | 74 sum += DELTA; |
75 v0 += ((v1 << 4) + sk0) ^ (v1 + sum) ^ ((v1 >> 5) + sk1); | |
76 v1 += ((v0 << 4) + sk2) ^ (v0 + sum) ^ ((v0 >> 5) + sk3); | |
77 } else { | |
78 v1 -= ((v0 << 4) + sk2) ^ (v0 + sum) ^ ((v0 >> 5) + sk3); | |
79 v0 -= ((v1 << 4) + sk0) ^ (v1 + sum) ^ ((v1 >> 5) + sk1); | |
80 sum -= DELTA; | |
81 } | |
82 } | |
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 | 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 | 88 } |
89 | |
90 /** Some TEA test vectors. */ | |
91 unittest { | |
92 static const char[][] test_keys = [ | |
93 "00000000000000000000000000000000", | |
94 "00000000000000000000000000000000", | |
95 "0123456712345678234567893456789a", | |
96 "0123456712345678234567893456789a" | |
97 ]; | |
98 | |
99 static const char[][] test_plaintexts = [ | |
100 "0000000000000000", | |
101 "0102030405060708", | |
102 "0000000000000000", | |
103 "0102030405060708" | |
104 ]; | |
105 | |
106 static const char[][] test_ciphertexts = [ | |
107 "41ea3a0a94baa940", | |
108 "6a2f9cf3fccf3c55", | |
109 "34e943b0900f5dcb", | |
110 "773dc179878a81c0" | |
111 ]; | |
112 | |
113 | |
114 TEA t = new TEA(); | |
115 foreach (uint i, char[] test_key; test_keys) { | |
116 ubyte[] buffer = new ubyte[t.blockSize]; | |
117 char[] result; | |
118 SymmetricKey key = new SymmetricKey(Util.hexToUbytes(test_key)); | |
119 | |
120 // Encryption | |
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 | 123 result = Util.ubytesToHex(buffer); |
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 | 126 |
127 // Decryption | |
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 | 130 result = Util.ubytesToHex(buffer); |
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 | 133 } |
134 } | |
135 } |