annotate dcrypt/crypto/ciphers/TEA.d @ 1:483e4467b5f6

Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
author Thomas Dixon <reikon@reikon.us>
date Tue, 12 Aug 2008 05:48:06 -0400
parents 0e08791a1418
children 71aae178f89a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
1 /**
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
2 * This file is part of the dcrypt project.
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
3 *
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
4 * Copyright: Copyright (C) dcrypt contributors 2008. All rights reserved.
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
5 * License: MIT
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
6 * Authors: Thomas Dixon
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
7 */
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
8
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
9 module dcrypt.crypto.ciphers.TEA;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
10
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
11 import dcrypt.misc.Util;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
12 import dcrypt.crypto.BlockCipher;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
13
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
14 /** Implementation of the TEA cipher designed by
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
15 David Wheeler and Roger Needham. */
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
16 class TEA : BlockCipher {
1
483e4467b5f6 Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents: 0
diff changeset
17 private {
483e4467b5f6 Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents: 0
diff changeset
18 const uint ROUNDS = 32,
483e4467b5f6 Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents: 0
diff changeset
19 KEY_SIZE = 16,
483e4467b5f6 Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents: 0
diff changeset
20 BLOCK_SIZE = 8,
483e4467b5f6 Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents: 0
diff changeset
21 DELTA = 0x9e3779b9,
483e4467b5f6 Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents: 0
diff changeset
22 DECRYPT_SUM = 0xc6ef3720;
483e4467b5f6 Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents: 0
diff changeset
23 uint sk0, sk1, sk2, sk3, sum;
483e4467b5f6 Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents: 0
diff changeset
24 bool initialized,
483e4467b5f6 Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents: 0
diff changeset
25 encrypt;
483e4467b5f6 Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents: 0
diff changeset
26 }
0
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
27
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
28 void reset(){}
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
29
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
30 char[] name() {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
31 return "TEA";
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
32 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
33
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
34 uint blockSize() {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
35 return BLOCK_SIZE;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
36 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
37
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
38 void init(bool encrypt, CipherParameters params) {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
39 SymmetricKey keyParams = cast(SymmetricKey)params;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
40 if (!keyParams)
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
41 throw new InvalidParameterError(
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
42 name()~": Invalid parameter passed to init");
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
43 this.encrypt = encrypt;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
44
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
45 if (keyParams.key.length != KEY_SIZE)
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
46 throw new InvalidKeyError(
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
47 name()~": Invalid key length (requires 16 bytes)");
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
48
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
49 sk0 = Util.ubytesToUintBig(keyParams.key, 0);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
50 sk1 = Util.ubytesToUintBig(keyParams.key, 4);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
51 sk2 = Util.ubytesToUintBig(keyParams.key, 8);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
52 sk3 = Util.ubytesToUintBig(keyParams.key, 12);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
53
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
54 initialized = true;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
55 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
56
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
57 uint processBlock(void[] input_, uint inOff, void[] output_, uint outOff) {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
58 if (!initialized)
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
59 throw new NotInitializedError(name()~": Cipher not initialized");
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
60
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
61 ubyte[] input = cast(ubyte[]) input_;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
62 ubyte[] output = cast(ubyte[]) output_;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
63
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
64 if ((inOff + BLOCK_SIZE) > input.length)
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
65 throw new ShortBufferError(name()~": Input buffer too short");
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
66
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
67 if ((outOff + BLOCK_SIZE) > output.length)
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
68 throw new ShortBufferError(name()~": Output buffer too short");
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
69
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
70 uint v0 = Util.ubytesToUintBig(input, inOff),
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
71 v1 = Util.ubytesToUintBig(input, inOff+4);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
72
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
73 sum = encrypt ? 0 : DECRYPT_SUM;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
74 for (int i = 0; i < ROUNDS; i++) {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
75 if (encrypt) {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
76 sum += DELTA;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
77 v0 += ((v1 << 4) + sk0) ^ (v1 + sum) ^ ((v1 >> 5) + sk1);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
78 v1 += ((v0 << 4) + sk2) ^ (v0 + sum) ^ ((v0 >> 5) + sk3);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
79 } else {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
80 v1 -= ((v0 << 4) + sk2) ^ (v0 + sum) ^ ((v0 >> 5) + sk3);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
81 v0 -= ((v1 << 4) + sk0) ^ (v1 + sum) ^ ((v1 >> 5) + sk1);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
82 sum -= DELTA;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
83 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
84 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
85
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
86 Util.uintToUbytesBig(v0, output, outOff);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
87 Util.uintToUbytesBig(v1, output, outOff+4);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
88
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
89 return BLOCK_SIZE;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
90 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
91
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
92 /** Some TEA test vectors. */
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
93 unittest {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
94 static const char[][] test_keys = [
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
95 "00000000000000000000000000000000",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
96 "00000000000000000000000000000000",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
97 "0123456712345678234567893456789a",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
98 "0123456712345678234567893456789a"
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
99 ];
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
100
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
101 static const char[][] test_plaintexts = [
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
102 "0000000000000000",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
103 "0102030405060708",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
104 "0000000000000000",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
105 "0102030405060708"
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
106 ];
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
107
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
108 static const char[][] test_ciphertexts = [
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
109 "41ea3a0a94baa940",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
110 "6a2f9cf3fccf3c55",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
111 "34e943b0900f5dcb",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
112 "773dc179878a81c0"
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
113 ];
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
114
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
115
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
116 TEA t = new TEA();
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
117 foreach (uint i, char[] test_key; test_keys) {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
118 ubyte[] buffer = new ubyte[t.blockSize];
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
119 char[] result;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
120 SymmetricKey key = new SymmetricKey(Util.hexToUbytes(test_key));
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
121
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
122 // Encryption
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
123 t.init(true, key);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
124 t.processBlock(Util.hexToUbytes(test_plaintexts[i]), 0, buffer, 0);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
125 result = Util.ubytesToHex(buffer);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
126 assert(result == test_ciphertexts[i],
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
127 t.name()~": ("~result~") != ("~test_ciphertexts[i]~")");
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
128
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
129 // Decryption
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
130 t.init(false, key);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
131 t.processBlock(Util.hexToUbytes(test_ciphertexts[i]), 0, buffer, 0);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
132 result = Util.ubytesToHex(buffer);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
133 assert(result == test_plaintexts[i],
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
134 t.name()~": ("~result~") != ("~test_ciphertexts[i]~")");
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
135 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
136 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
137 }