annotate dcrypt/crypto/ciphers/XTEA.d @ 0:0e08791a1418

Initial import.
author Thomas Dixon <reikon@reikon.us>
date Sun, 10 Aug 2008 14:20:17 -0400
parents
children 483e4467b5f6
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.XTEA;
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 XTEA 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 XTEA : BlockCipher {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
17 private const uint ROUNDS = 32,
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
18 KEY_SIZE = 16,
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
19 BLOCK_SIZE = 8,
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
20 DELTA = 0x9e3779b9;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
21 private uint[] subkeys,
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
22 sum0,
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
23 sum1;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
24 private bool initialized,
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
25 encrypt;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
26
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
27 void reset(){}
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
28
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
29 char[] name() {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
30 return "XTEA";
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
31 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
32
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
33 uint blockSize() {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
34 return BLOCK_SIZE;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
35 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
36
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
37 void init(bool encrypt, CipherParameters params) {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
38 SymmetricKey keyParams = cast(SymmetricKey)params;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
39 if (!keyParams)
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
40 throw new InvalidParameterError(
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
41 name()~": Invalid parameter passed to init");
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
42 this.encrypt = encrypt;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
43
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
44 if (keyParams.key.length != KEY_SIZE)
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
45 throw new InvalidKeyError(
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
46 name()~": Invalid key length (requires 16 bytes)");
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
47
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
48 subkeys = new uint[4];
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
49 sum0 = new uint[32];
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
50 sum1 = new uint[32];
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
51
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
52 int i, j;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
53 for (i = j = 0; i < 4; i++, j+=4)
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
54 subkeys[i] = Util.ubytesToUintBig(keyParams.key, j);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
55
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
56 // Precompute the values of sum + k[] to speed up encryption
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
57 for (i = j = 0; i < ROUNDS; i++) {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
58 sum0[i] = (j + subkeys[j & 3]);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
59 j += DELTA;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
60 sum1[i] = (j + subkeys[j >> 11 & 3]);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
61 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
62 initialized = true;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
63 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
64
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
65 uint processBlock(void[] input_, uint inOff, void[] output_, uint outOff) {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
66 if (!initialized)
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
67 throw new NotInitializedError(name()~": Cipher not initialized");
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
68
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
69 ubyte[] input = cast(ubyte[]) input_;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
70 ubyte[] output = cast(ubyte[]) output_;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
71
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
72 if ((inOff + BLOCK_SIZE) > input.length)
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
73 throw new ShortBufferError(name()~": Input buffer too short");
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
74
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
75 if ((outOff + BLOCK_SIZE) > output.length)
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
76 throw new ShortBufferError(name()~": Output buffer too short");
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
77
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
78 uint v0 = Util.ubytesToUintBig(input, inOff),
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
79 v1 = Util.ubytesToUintBig(input, inOff+4);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
80
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
81 if (encrypt) {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
82 for (int i = 0; i < ROUNDS; i++) {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
83 v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ sum0[i];
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
84 v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ sum1[i];
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
85 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
86 } else {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
87 for (int i = ROUNDS-1; i >= 0; i--) {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
88 v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ sum1[i];
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
89 v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ sum0[i];
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
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
93 Util.uintToUbytesBig(v0, output, outOff);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
94 Util.uintToUbytesBig(v1, output, outOff+4);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
95
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
96 return BLOCK_SIZE;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
97 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
98
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
99 /** Some XTEA test vectors. */
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
100 version (UnitTest) {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
101 unittest {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
102 static const char[][] test_keys = [
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
103 "00000000000000000000000000000000",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
104 "00000000000000000000000000000000",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
105 "0123456712345678234567893456789a",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
106 "0123456712345678234567893456789a",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
107 "00000000000000000000000000000001",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
108 "01010101010101010101010101010101",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
109 "0123456789abcdef0123456789abcdef",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
110 "0123456789abcdef0123456789abcdef",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
111 "00000000000000000000000000000000",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
112 "00000000000000000000000000000000"
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 static const char[][] test_plaintexts = [
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
116 "0000000000000000",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
117 "0102030405060708",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
118 "0000000000000000",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
119 "0102030405060708",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
120 "0000000000000001",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
121 "0101010101010101",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
122 "0123456789abcdef",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
123 "0000000000000000",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
124 "0123456789abcdef",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
125 "4141414141414141"
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
126 ];
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
127
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
128 static const char[][] test_ciphertexts = [
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
129 "dee9d4d8f7131ed9",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
130 "065c1b8975c6a816",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
131 "1ff9a0261ac64264",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
132 "8c67155b2ef91ead",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
133 "9f25fa5b0f86b758",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
134 "c2eca7cec9b7f992",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
135 "27e795e076b2b537",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
136 "5c8eddc60a95b3e1",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
137 "7e66c71c88897221",
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
138 "ed23375a821a8c2d"
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
139 ];
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
140
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
141 XTEA t = new XTEA();
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
142 foreach (uint i, char[] test_key; test_keys) {
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
143 ubyte[] buffer = new ubyte[t.blockSize];
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
144 char[] result;
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
145 SymmetricKey key = new SymmetricKey(Util.hexToUbytes(test_key));
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
146
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
147 // Encryption
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
148 t.init(true, key);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
149 t.processBlock(Util.hexToUbytes(test_plaintexts[i]), 0, buffer, 0);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
150 result = Util.ubytesToHex(buffer);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
151 assert(result == test_ciphertexts[i],
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
152 t.name()~": ("~result~") != ("~test_ciphertexts[i]~")");
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
153
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
154 // Decryption
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
155 t.init(false, key);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
156 t.processBlock(Util.hexToUbytes(test_ciphertexts[i]), 0, buffer, 0);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
157 result = Util.ubytesToHex(buffer);
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
158 assert(result == test_plaintexts[i],
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
159 t.name()~": ("~result~") != ("~test_ciphertexts[i]~")");
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
160 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
161 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
162 }
0e08791a1418 Initial import.
Thomas Dixon <reikon@reikon.us>
parents:
diff changeset
163 }