Mercurial > projects > dcrypt
comparison 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 |
comparison
equal
deleted
inserted
replaced
26:176c933827a8 | 27:8b5eaf3c2979 |
---|---|
11 import dcrypt.misc.ByteConverter; | 11 import dcrypt.misc.ByteConverter; |
12 import dcrypt.crypto.BlockCipher; | 12 import dcrypt.crypto.BlockCipher; |
13 | 13 |
14 /** Implementation of the XTEA cipher designed by | 14 /** Implementation of the XTEA cipher designed by |
15 David Wheeler and Roger Needham. */ | 15 David Wheeler and Roger Needham. */ |
16 class XTEA : BlockCipher { | 16 class XTEA : BlockCipher |
17 private { | 17 { |
18 private | |
19 { | |
18 const uint ROUNDS = 32, | 20 const uint ROUNDS = 32, |
19 KEY_SIZE = 16, | 21 KEY_SIZE = 16, |
20 BLOCK_SIZE = 8, | 22 BLOCK_SIZE = 8, |
21 DELTA = 0x9e3779b9; | 23 DELTA = 0x9e3779b9u; |
22 uint[] subkeys, | 24 uint[] subkeys, |
23 sum0, | 25 sum0, |
24 sum1; | 26 sum1; |
25 } | 27 } |
26 | 28 |
27 void reset(){} | 29 void reset(){} |
28 | 30 |
29 char[] name() { | 31 char[] name() |
32 { | |
30 return "XTEA"; | 33 return "XTEA"; |
31 } | 34 } |
32 | 35 |
33 uint blockSize() { | 36 uint blockSize() |
37 { | |
34 return BLOCK_SIZE; | 38 return BLOCK_SIZE; |
35 } | 39 } |
36 | 40 |
37 void init(bool encrypt, CipherParameters params) { | 41 void init(bool encrypt, CipherParameters params) |
42 { | |
38 SymmetricKey keyParams = cast(SymmetricKey)params; | 43 SymmetricKey keyParams = cast(SymmetricKey)params; |
39 if (!keyParams) | 44 if (!keyParams) |
40 throw new InvalidParameterError( | 45 throw new InvalidParameterError( |
41 name()~": Invalid parameter passed to init"); | 46 name()~": Invalid parameter passed to init"); |
47 | |
42 _encrypt = encrypt; | 48 _encrypt = encrypt; |
43 | 49 |
44 if (keyParams.key.length != KEY_SIZE) | 50 if (keyParams.key.length != KEY_SIZE) |
45 throw new InvalidKeyError( | 51 throw new InvalidKeyError( |
46 name()~": Invalid key length (requires 16 bytes)"); | 52 name()~": Invalid key length (requires 16 bytes)"); |
52 int i, j; | 58 int i, j; |
53 for (i = j = 0; i < 4; i++, j+=int.sizeof) | 59 for (i = j = 0; i < 4; i++, j+=int.sizeof) |
54 subkeys[i] = ByteConverter.BigEndian.to!(uint)(keyParams.key[j..j+int.sizeof]); | 60 subkeys[i] = ByteConverter.BigEndian.to!(uint)(keyParams.key[j..j+int.sizeof]); |
55 | 61 |
56 // Precompute the values of sum + k[] to speed up encryption | 62 // Precompute the values of sum + k[] to speed up encryption |
57 for (i = j = 0; i < ROUNDS; i++) { | 63 for (i = j = 0; i < ROUNDS; i++) |
64 { | |
58 sum0[i] = (j + subkeys[j & 3]); | 65 sum0[i] = (j + subkeys[j & 3]); |
59 j += DELTA; | 66 j += DELTA; |
60 sum1[i] = (j + subkeys[j >> 11 & 3]); | 67 sum1[i] = (j + subkeys[j >> 11 & 3]); |
61 } | 68 } |
69 | |
62 _initialized = true; | 70 _initialized = true; |
63 } | 71 } |
64 | 72 |
65 uint update(void[] input_, void[] output_) { | 73 uint update(void[] input_, void[] output_) |
74 { | |
66 if (!_initialized) | 75 if (!_initialized) |
67 throw new NotInitializedError(name()~": Cipher not initialized"); | 76 throw new NotInitializedError(name()~": Cipher not initialized"); |
68 | 77 |
69 ubyte[] input = cast(ubyte[]) input_, | 78 ubyte[] input = cast(ubyte[]) input_, |
70 output = cast(ubyte[]) output_; | 79 output = cast(ubyte[]) output_; |
76 throw new ShortBufferError(name()~": Output buffer too short"); | 85 throw new ShortBufferError(name()~": Output buffer too short"); |
77 | 86 |
78 uint v0 = ByteConverter.BigEndian.to!(uint)(input[0..4]), | 87 uint v0 = ByteConverter.BigEndian.to!(uint)(input[0..4]), |
79 v1 = ByteConverter.BigEndian.to!(uint)(input[4..8]); | 88 v1 = ByteConverter.BigEndian.to!(uint)(input[4..8]); |
80 | 89 |
81 if (_encrypt) { | 90 if (_encrypt) |
82 for (int i = 0; i < ROUNDS; i++) { | 91 { |
92 for (int i = 0; i < ROUNDS; i++) | |
93 { | |
83 v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ sum0[i]; | 94 v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ sum0[i]; |
84 v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ sum1[i]; | 95 v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ sum1[i]; |
85 } | 96 } |
86 } else { | 97 } |
87 for (int i = ROUNDS-1; i >= 0; i--) { | 98 else |
99 { | |
100 for (int i = ROUNDS-1; i >= 0; i--) | |
101 { | |
88 v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ sum1[i]; | 102 v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ sum1[i]; |
89 v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ sum0[i]; | 103 v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ sum0[i]; |
90 } | 104 } |
91 } | 105 } |
92 | 106 |
95 | 109 |
96 return BLOCK_SIZE; | 110 return BLOCK_SIZE; |
97 } | 111 } |
98 | 112 |
99 /** Some XTEA test vectors. */ | 113 /** Some XTEA test vectors. */ |
100 debug (UnitTest) { | 114 debug (UnitTest) |
101 unittest { | 115 { |
116 unittest | |
117 { | |
102 static const char[][] test_keys = [ | 118 static const char[][] test_keys = [ |
103 "00000000000000000000000000000000", | 119 "00000000000000000000000000000000", |
104 "00000000000000000000000000000000", | 120 "00000000000000000000000000000000", |
105 "0123456712345678234567893456789a", | 121 "0123456712345678234567893456789a", |
106 "0123456712345678234567893456789a", | 122 "0123456712345678234567893456789a", |
137 "7e66c71c88897221", | 153 "7e66c71c88897221", |
138 "ed23375a821a8c2d" | 154 "ed23375a821a8c2d" |
139 ]; | 155 ]; |
140 | 156 |
141 XTEA t = new XTEA(); | 157 XTEA t = new XTEA(); |
142 foreach (uint i, char[] test_key; test_keys) { | 158 foreach (uint i, char[] test_key; test_keys) |
159 { | |
143 ubyte[] buffer = new ubyte[t.blockSize]; | 160 ubyte[] buffer = new ubyte[t.blockSize]; |
144 char[] result; | 161 char[] result; |
145 SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_key)); | 162 SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_key)); |
146 | 163 |
147 // Encryption | 164 // Encryption |