Mercurial > projects > dcrypt
annotate dcrypt/crypto/ciphers/XTEA.d @ 27:8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
author | Thomas Dixon <reikon@reikon.us> |
---|---|
date | Sat, 09 May 2009 23:29:20 -0400 |
parents | 176c933827a8 |
children | ad687db713a4 |
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.XTEA; | |
10 | |
23
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
11 import dcrypt.misc.ByteConverter; |
0 | 12 import dcrypt.crypto.BlockCipher; |
13 | |
14 /** Implementation of the XTEA cipher designed by | |
15 David Wheeler and Roger Needham. */ | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
16 class XTEA : BlockCipher |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
17 { |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
18 private |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
19 { |
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
|
20 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
|
21 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
|
22 BLOCK_SIZE = 8, |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
23 DELTA = 0x9e3779b9u; |
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
|
24 uint[] subkeys, |
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
|
25 sum0, |
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
|
26 sum1; |
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
|
27 } |
0 | 28 |
29 void reset(){} | |
30 | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
31 char[] name() |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
32 { |
0 | 33 return "XTEA"; |
34 } | |
35 | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
36 uint blockSize() |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
37 { |
0 | 38 return BLOCK_SIZE; |
39 } | |
40 | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
41 void init(bool encrypt, CipherParameters params) |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
42 { |
0 | 43 SymmetricKey keyParams = cast(SymmetricKey)params; |
44 if (!keyParams) | |
45 throw new InvalidParameterError( | |
46 name()~": Invalid parameter passed to init"); | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
47 |
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
|
48 _encrypt = encrypt; |
0 | 49 |
50 if (keyParams.key.length != KEY_SIZE) | |
51 throw new InvalidKeyError( | |
52 name()~": Invalid key length (requires 16 bytes)"); | |
53 | |
54 subkeys = new uint[4]; | |
55 sum0 = new uint[32]; | |
56 sum1 = new uint[32]; | |
57 | |
58 int i, j; | |
23
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
59 for (i = j = 0; i < 4; i++, j+=int.sizeof) |
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
60 subkeys[i] = ByteConverter.BigEndian.to!(uint)(keyParams.key[j..j+int.sizeof]); |
0 | 61 |
62 // Precompute the values of sum + k[] to speed up encryption | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
63 for (i = j = 0; i < ROUNDS; i++) |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
64 { |
0 | 65 sum0[i] = (j + subkeys[j & 3]); |
66 j += DELTA; | |
67 sum1[i] = (j + subkeys[j >> 11 & 3]); | |
68 } | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
69 |
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
|
70 _initialized = true; |
0 | 71 } |
72 | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
73 uint update(void[] input_, void[] output_) |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
74 { |
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
|
75 if (!_initialized) |
0 | 76 throw new NotInitializedError(name()~": Cipher not initialized"); |
77 | |
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
|
78 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
|
79 output = cast(ubyte[]) output_; |
0 | 80 |
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
|
81 if (input.length < BLOCK_SIZE) |
0 | 82 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
|
83 |
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
|
84 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
|
85 throw new ShortBufferError(name()~": Output buffer too short"); |
0 | 86 |
23
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
87 uint v0 = ByteConverter.BigEndian.to!(uint)(input[0..4]), |
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
88 v1 = ByteConverter.BigEndian.to!(uint)(input[4..8]); |
0 | 89 |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
90 if (_encrypt) |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
91 { |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
92 for (int i = 0; i < ROUNDS; i++) |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
93 { |
0 | 94 v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ sum0[i]; |
95 v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ sum1[i]; | |
96 } | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
97 } |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
98 else |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
99 { |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
100 for (int i = ROUNDS-1; i >= 0; i--) |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
101 { |
0 | 102 v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ sum1[i]; |
103 v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ sum0[i]; | |
104 } | |
105 } | |
106 | |
23
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
107 output[0..4] = ByteConverter.BigEndian.from!(uint)(v0); |
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
108 output[4..8] = ByteConverter.BigEndian.from!(uint)(v1); |
0 | 109 |
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
|
110 return BLOCK_SIZE; |
0 | 111 } |
112 | |
113 /** Some XTEA test vectors. */ | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
114 debug (UnitTest) |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
115 { |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
116 unittest |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
117 { |
0 | 118 static const char[][] test_keys = [ |
119 "00000000000000000000000000000000", | |
120 "00000000000000000000000000000000", | |
121 "0123456712345678234567893456789a", | |
122 "0123456712345678234567893456789a", | |
123 "00000000000000000000000000000001", | |
124 "01010101010101010101010101010101", | |
125 "0123456789abcdef0123456789abcdef", | |
126 "0123456789abcdef0123456789abcdef", | |
127 "00000000000000000000000000000000", | |
128 "00000000000000000000000000000000" | |
129 ]; | |
130 | |
131 static const char[][] test_plaintexts = [ | |
132 "0000000000000000", | |
133 "0102030405060708", | |
134 "0000000000000000", | |
135 "0102030405060708", | |
136 "0000000000000001", | |
137 "0101010101010101", | |
138 "0123456789abcdef", | |
139 "0000000000000000", | |
140 "0123456789abcdef", | |
141 "4141414141414141" | |
142 ]; | |
143 | |
144 static const char[][] test_ciphertexts = [ | |
145 "dee9d4d8f7131ed9", | |
146 "065c1b8975c6a816", | |
147 "1ff9a0261ac64264", | |
148 "8c67155b2ef91ead", | |
149 "9f25fa5b0f86b758", | |
150 "c2eca7cec9b7f992", | |
151 "27e795e076b2b537", | |
152 "5c8eddc60a95b3e1", | |
153 "7e66c71c88897221", | |
154 "ed23375a821a8c2d" | |
155 ]; | |
156 | |
157 XTEA t = new XTEA(); | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
158 foreach (uint i, char[] test_key; test_keys) |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
159 { |
0 | 160 ubyte[] buffer = new ubyte[t.blockSize]; |
161 char[] result; | |
23
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
162 SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_key)); |
0 | 163 |
164 // Encryption | |
165 t.init(true, key); | |
23
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
166 t.update(ByteConverter.hexDecode(test_plaintexts[i]), buffer); |
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
167 result = ByteConverter.hexEncode(buffer); |
0 | 168 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
|
169 t.name~": ("~result~") != ("~test_ciphertexts[i]~")"); |
0 | 170 |
171 // Decryption | |
172 t.init(false, key); | |
23
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
173 t.update(ByteConverter.hexDecode(test_ciphertexts[i]), buffer); |
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
174 result = ByteConverter.hexEncode(buffer); |
0 | 175 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
|
176 t.name~": ("~result~") != ("~test_plaintexts[i]~")"); |
0 | 177 } |
178 } | |
179 } | |
180 } |