Mercurial > projects > dcrypt
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 } |