comparison dcrypt/crypto/ciphers/TEA.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 4589f8c5eb3c
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 TEA cipher designed by 14 /** Implementation of the TEA cipher designed by
15 David Wheeler and Roger Needham. */ 15 David Wheeler and Roger Needham. */
16 class TEA : BlockCipher { 16 class TEA : 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 DECRYPT_SUM = 0xc6ef3720; 24 DECRYPT_SUM = 0xc6ef3720u;
23 uint sk0, sk1, sk2, sk3, sum; 25 uint sk0, sk1, sk2, sk3, sum;
24 } 26 }
25 27
26 void reset(){} 28 void reset(){}
27 29
28 char[] name() { 30 char[] name()
31 {
29 return "TEA"; 32 return "TEA";
30 } 33 }
31 34
32 uint blockSize() { 35 uint blockSize()
36 {
33 return BLOCK_SIZE; 37 return BLOCK_SIZE;
34 } 38 }
35 39
36 void init(bool encrypt, CipherParameters params) { 40 void init(bool encrypt, CipherParameters params)
41 {
37 SymmetricKey keyParams = cast(SymmetricKey)params; 42 SymmetricKey keyParams = cast(SymmetricKey)params;
38 if (!keyParams) 43 if (!keyParams)
39 throw new InvalidParameterError( 44 throw new InvalidParameterError(
40 name()~": Invalid parameter passed to init"); 45 name()~": Invalid parameter passed to init");
46
41 _encrypt = encrypt; 47 _encrypt = encrypt;
42 48
43 if (keyParams.key.length != KEY_SIZE) 49 if (keyParams.key.length != KEY_SIZE)
44 throw new InvalidKeyError( 50 throw new InvalidKeyError(
45 name()~": Invalid key length (requires 16 bytes)"); 51 name()~": Invalid key length (requires 16 bytes)");
50 sk3 = ByteConverter.BigEndian.to!(uint)(keyParams.key[12..16]); 56 sk3 = ByteConverter.BigEndian.to!(uint)(keyParams.key[12..16]);
51 57
52 _initialized = true; 58 _initialized = true;
53 } 59 }
54 60
55 uint update(void[] input_, void[] output_) { 61 uint update(void[] input_, void[] output_)
62 {
56 if (!_initialized) 63 if (!_initialized)
57 throw new NotInitializedError(name()~": Cipher not initialized"); 64 throw new NotInitializedError(name()~": Cipher not initialized");
58 65
59 ubyte[] input = cast(ubyte[]) input_, 66 ubyte[] input = cast(ubyte[]) input_,
60 output = cast(ubyte[]) output_; 67 output = cast(ubyte[]) output_;
67 74
68 uint v0 = ByteConverter.BigEndian.to!(uint)(input[0..4]), 75 uint v0 = ByteConverter.BigEndian.to!(uint)(input[0..4]),
69 v1 = ByteConverter.BigEndian.to!(uint)(input[4..8]); 76 v1 = ByteConverter.BigEndian.to!(uint)(input[4..8]);
70 77
71 sum = _encrypt ? 0 : DECRYPT_SUM; 78 sum = _encrypt ? 0 : DECRYPT_SUM;
72 for (int i = 0; i < ROUNDS; i++) { 79 for (int i = 0; i < ROUNDS; i++)
73 if (_encrypt) { 80 {
81 if (_encrypt)
82 {
74 sum += DELTA; 83 sum += DELTA;
75 v0 += ((v1 << 4) + sk0) ^ (v1 + sum) ^ ((v1 >> 5) + sk1); 84 v0 += ((v1 << 4) + sk0) ^ (v1 + sum) ^ ((v1 >> 5) + sk1);
76 v1 += ((v0 << 4) + sk2) ^ (v0 + sum) ^ ((v0 >> 5) + sk3); 85 v1 += ((v0 << 4) + sk2) ^ (v0 + sum) ^ ((v0 >> 5) + sk3);
77 } else { 86 }
87 else
88 {
78 v1 -= ((v0 << 4) + sk2) ^ (v0 + sum) ^ ((v0 >> 5) + sk3); 89 v1 -= ((v0 << 4) + sk2) ^ (v0 + sum) ^ ((v0 >> 5) + sk3);
79 v0 -= ((v1 << 4) + sk0) ^ (v1 + sum) ^ ((v1 >> 5) + sk1); 90 v0 -= ((v1 << 4) + sk0) ^ (v1 + sum) ^ ((v1 >> 5) + sk1);
80 sum -= DELTA; 91 sum -= DELTA;
81 } 92 }
82 } 93 }
86 97
87 return BLOCK_SIZE; 98 return BLOCK_SIZE;
88 } 99 }
89 100
90 /** Some TEA test vectors. */ 101 /** Some TEA test vectors. */
91 unittest { 102 debug (UnitTest)
92 static const char[][] test_keys = [ 103 {
93 "00000000000000000000000000000000", 104 unittest
94 "00000000000000000000000000000000", 105 {
95 "0123456712345678234567893456789a", 106 static const char[][] test_keys = [
96 "0123456712345678234567893456789a" 107 "00000000000000000000000000000000",
97 ]; 108 "00000000000000000000000000000000",
98 109 "0123456712345678234567893456789a",
99 static const char[][] test_plaintexts = [ 110 "0123456712345678234567893456789a"
100 "0000000000000000", 111 ];
101 "0102030405060708", 112
102 "0000000000000000", 113 static const char[][] test_plaintexts = [
103 "0102030405060708" 114 "0000000000000000",
104 ]; 115 "0102030405060708",
116 "0000000000000000",
117 "0102030405060708"
118 ];
119
120 static const char[][] test_ciphertexts = [
121 "41ea3a0a94baa940",
122 "6a2f9cf3fccf3c55",
123 "34e943b0900f5dcb",
124 "773dc179878a81c0"
125 ];
126
105 127
106 static const char[][] test_ciphertexts = [ 128 TEA t = new TEA();
107 "41ea3a0a94baa940", 129 foreach (uint i, char[] test_key; test_keys)
108 "6a2f9cf3fccf3c55", 130 {
109 "34e943b0900f5dcb", 131 ubyte[] buffer = new ubyte[t.blockSize];
110 "773dc179878a81c0" 132 char[] result;
111 ]; 133 SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_key));
112 134
113 135 // Encryption
114 TEA t = new TEA(); 136 t.init(true, key);
115 foreach (uint i, char[] test_key; test_keys) { 137 t.update(ByteConverter.hexDecode(test_plaintexts[i]), buffer);
116 ubyte[] buffer = new ubyte[t.blockSize]; 138 result = ByteConverter.hexEncode(buffer);
117 char[] result; 139 assert(result == test_ciphertexts[i],
118 SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_key)); 140 t.name~": ("~result~") != ("~test_ciphertexts[i]~")");
119
120 // Encryption
121 t.init(true, key);
122 t.update(ByteConverter.hexDecode(test_plaintexts[i]), buffer);
123 result = ByteConverter.hexEncode(buffer);
124 assert(result == test_ciphertexts[i],
125 t.name~": ("~result~") != ("~test_ciphertexts[i]~")");
126 141
127 // Decryption 142 // Decryption
128 t.init(false, key); 143 t.init(false, key);
129 t.update(ByteConverter.hexDecode(test_ciphertexts[i]), buffer); 144 t.update(ByteConverter.hexDecode(test_ciphertexts[i]), buffer);
130 result = ByteConverter.hexEncode(buffer); 145 result = ByteConverter.hexEncode(buffer);
131 assert(result == test_plaintexts[i], 146 assert(result == test_plaintexts[i],
132 t.name~": ("~result~") != ("~test_plaintexts[i]~")"); 147 t.name~": ("~result~") != ("~test_plaintexts[i]~")");
148 }
133 } 149 }
134 } 150 }
135 } 151 }