Mercurial > projects > dcrypt
comparison dcrypt/crypto/ciphers/TEA.d @ 0:0e08791a1418
Initial import.
author | Thomas Dixon <reikon@reikon.us> |
---|---|
date | Sun, 10 Aug 2008 14:20:17 -0400 |
parents | |
children | 483e4467b5f6 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:0e08791a1418 |
---|---|
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.TEA; | |
10 | |
11 import dcrypt.misc.Util; | |
12 import dcrypt.crypto.BlockCipher; | |
13 | |
14 /** Implementation of the TEA cipher designed by | |
15 David Wheeler and Roger Needham. */ | |
16 class TEA : BlockCipher { | |
17 private const uint ROUNDS = 32, | |
18 KEY_SIZE = 16, | |
19 BLOCK_SIZE = 8, | |
20 DELTA = 0x9e3779b9, | |
21 DECRYPT_SUM = 0xc6ef3720; | |
22 private uint sk0, sk1, sk2, sk3, sum; | |
23 private bool initialized, | |
24 encrypt; | |
25 | |
26 void reset(){} | |
27 | |
28 char[] name() { | |
29 return "TEA"; | |
30 } | |
31 | |
32 uint blockSize() { | |
33 return BLOCK_SIZE; | |
34 } | |
35 | |
36 void init(bool encrypt, CipherParameters params) { | |
37 SymmetricKey keyParams = cast(SymmetricKey)params; | |
38 if (!keyParams) | |
39 throw new InvalidParameterError( | |
40 name()~": Invalid parameter passed to init"); | |
41 this.encrypt = encrypt; | |
42 | |
43 if (keyParams.key.length != KEY_SIZE) | |
44 throw new InvalidKeyError( | |
45 name()~": Invalid key length (requires 16 bytes)"); | |
46 | |
47 sk0 = Util.ubytesToUintBig(keyParams.key, 0); | |
48 sk1 = Util.ubytesToUintBig(keyParams.key, 4); | |
49 sk2 = Util.ubytesToUintBig(keyParams.key, 8); | |
50 sk3 = Util.ubytesToUintBig(keyParams.key, 12); | |
51 | |
52 initialized = true; | |
53 } | |
54 | |
55 uint processBlock(void[] input_, uint inOff, void[] output_, uint outOff) { | |
56 if (!initialized) | |
57 throw new NotInitializedError(name()~": Cipher not initialized"); | |
58 | |
59 ubyte[] input = cast(ubyte[]) input_; | |
60 ubyte[] output = cast(ubyte[]) output_; | |
61 | |
62 if ((inOff + BLOCK_SIZE) > input.length) | |
63 throw new ShortBufferError(name()~": Input buffer too short"); | |
64 | |
65 if ((outOff + BLOCK_SIZE) > output.length) | |
66 throw new ShortBufferError(name()~": Output buffer too short"); | |
67 | |
68 uint v0 = Util.ubytesToUintBig(input, inOff), | |
69 v1 = Util.ubytesToUintBig(input, inOff+4); | |
70 | |
71 sum = encrypt ? 0 : DECRYPT_SUM; | |
72 for (int i = 0; i < ROUNDS; i++) { | |
73 if (encrypt) { | |
74 sum += DELTA; | |
75 v0 += ((v1 << 4) + sk0) ^ (v1 + sum) ^ ((v1 >> 5) + sk1); | |
76 v1 += ((v0 << 4) + sk2) ^ (v0 + sum) ^ ((v0 >> 5) + sk3); | |
77 } else { | |
78 v1 -= ((v0 << 4) + sk2) ^ (v0 + sum) ^ ((v0 >> 5) + sk3); | |
79 v0 -= ((v1 << 4) + sk0) ^ (v1 + sum) ^ ((v1 >> 5) + sk1); | |
80 sum -= DELTA; | |
81 } | |
82 } | |
83 | |
84 Util.uintToUbytesBig(v0, output, outOff); | |
85 Util.uintToUbytesBig(v1, output, outOff+4); | |
86 | |
87 return BLOCK_SIZE; | |
88 } | |
89 | |
90 /** Some TEA test vectors. */ | |
91 unittest { | |
92 static const char[][] test_keys = [ | |
93 "00000000000000000000000000000000", | |
94 "00000000000000000000000000000000", | |
95 "0123456712345678234567893456789a", | |
96 "0123456712345678234567893456789a" | |
97 ]; | |
98 | |
99 static const char[][] test_plaintexts = [ | |
100 "0000000000000000", | |
101 "0102030405060708", | |
102 "0000000000000000", | |
103 "0102030405060708" | |
104 ]; | |
105 | |
106 static const char[][] test_ciphertexts = [ | |
107 "41ea3a0a94baa940", | |
108 "6a2f9cf3fccf3c55", | |
109 "34e943b0900f5dcb", | |
110 "773dc179878a81c0" | |
111 ]; | |
112 | |
113 | |
114 TEA t = new TEA(); | |
115 foreach (uint i, char[] test_key; test_keys) { | |
116 ubyte[] buffer = new ubyte[t.blockSize]; | |
117 char[] result; | |
118 SymmetricKey key = new SymmetricKey(Util.hexToUbytes(test_key)); | |
119 | |
120 // Encryption | |
121 t.init(true, key); | |
122 t.processBlock(Util.hexToUbytes(test_plaintexts[i]), 0, buffer, 0); | |
123 result = Util.ubytesToHex(buffer); | |
124 assert(result == test_ciphertexts[i], | |
125 t.name()~": ("~result~") != ("~test_ciphertexts[i]~")"); | |
126 | |
127 // Decryption | |
128 t.init(false, key); | |
129 t.processBlock(Util.hexToUbytes(test_ciphertexts[i]), 0, buffer, 0); | |
130 result = Util.ubytesToHex(buffer); | |
131 assert(result == test_plaintexts[i], | |
132 t.name()~": ("~result~") != ("~test_ciphertexts[i]~")"); | |
133 } | |
134 } | |
135 } |