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