Mercurial > projects > dcrypt
annotate dcrypt/crypto/ciphers/XTEA.d @ 23:4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
author | Thomas Dixon <reikon@reikon.us> |
---|---|
date | Sat, 14 Feb 2009 19:58:20 -0500 |
parents | 5ce3012f1def |
children | 176c933827a8 |
rev | line source |
---|---|
0 | 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.XTEA; | |
10 | |
23
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
11 import dcrypt.misc.ByteConverter; |
0 | 12 import dcrypt.crypto.BlockCipher; |
13 | |
14 /** Implementation of the XTEA cipher designed by | |
15 David Wheeler and Roger Needham. */ | |
16 class XTEA : 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 uint[] subkeys, |
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 sum0, |
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 sum1; |
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 } |
0 | 26 |
27 void reset(){} | |
28 | |
29 char[] name() { | |
30 return "XTEA"; | |
31 } | |
32 | |
33 uint blockSize() { | |
34 return BLOCK_SIZE; | |
35 } | |
36 | |
37 void init(bool encrypt, CipherParameters params) { | |
38 SymmetricKey keyParams = cast(SymmetricKey)params; | |
39 if (!keyParams) | |
40 throw new InvalidParameterError( | |
41 name()~": Invalid parameter passed to init"); | |
14
5ce3012f1def
Removed some redundancy in code. Added NotSupportedError, a base PRNG class and a class which creates a PRNG from a hash function. Changed the MAC class' finalization methods to digest and hexDigest instead of finish and hexFinish respectively. Also added a base Checksum class, crc32 and adler32 in dcrypt.misc as per request.
Thomas Dixon <reikon@reikon.us>
parents:
12
diff
changeset
|
42 _encrypt = encrypt; |
0 | 43 |
44 if (keyParams.key.length != KEY_SIZE) | |
45 throw new InvalidKeyError( | |
46 name()~": Invalid key length (requires 16 bytes)"); | |
47 | |
48 subkeys = new uint[4]; | |
49 sum0 = new uint[32]; | |
50 sum1 = new uint[32]; | |
51 | |
52 int i, j; | |
23
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
53 for (i = j = 0; i < 4; i++, j+=int.sizeof) |
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
54 subkeys[i] = ByteConverter.BigEndian.to!(uint)(keyParams.key[j..j+int.sizeof]); |
0 | 55 |
56 // Precompute the values of sum + k[] to speed up encryption | |
57 for (i = j = 0; i < ROUNDS; i++) { | |
58 sum0[i] = (j + subkeys[j & 3]); | |
59 j += DELTA; | |
60 sum1[i] = (j + subkeys[j >> 11 & 3]); | |
61 } | |
14
5ce3012f1def
Removed some redundancy in code. Added NotSupportedError, a base PRNG class and a class which creates a PRNG from a hash function. Changed the MAC class' finalization methods to digest and hexDigest instead of finish and hexFinish respectively. Also added a base Checksum class, crc32 and adler32 in dcrypt.misc as per request.
Thomas Dixon <reikon@reikon.us>
parents:
12
diff
changeset
|
62 _initialized = true; |
0 | 63 } |
64 | |
12
8c7f8fecdd75
Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents:
8
diff
changeset
|
65 uint update(void[] input_, void[] output_) { |
14
5ce3012f1def
Removed some redundancy in code. Added NotSupportedError, a base PRNG class and a class which creates a PRNG from a hash function. Changed the MAC class' finalization methods to digest and hexDigest instead of finish and hexFinish respectively. Also added a base Checksum class, crc32 and adler32 in dcrypt.misc as per request.
Thomas Dixon <reikon@reikon.us>
parents:
12
diff
changeset
|
66 if (!_initialized) |
0 | 67 throw new NotInitializedError(name()~": Cipher not initialized"); |
68 | |
12
8c7f8fecdd75
Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents:
8
diff
changeset
|
69 ubyte[] input = cast(ubyte[]) input_, |
8c7f8fecdd75
Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents:
8
diff
changeset
|
70 output = cast(ubyte[]) output_; |
0 | 71 |
12
8c7f8fecdd75
Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents:
8
diff
changeset
|
72 if (input.length < BLOCK_SIZE) |
0 | 73 throw new ShortBufferError(name()~": Input buffer too short"); |
12
8c7f8fecdd75
Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents:
8
diff
changeset
|
74 |
8c7f8fecdd75
Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents:
8
diff
changeset
|
75 if (output.length < BLOCK_SIZE) |
8c7f8fecdd75
Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents:
8
diff
changeset
|
76 throw new ShortBufferError(name()~": Output buffer too short"); |
0 | 77 |
23
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
78 uint v0 = ByteConverter.BigEndian.to!(uint)(input[0..4]), |
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
79 v1 = ByteConverter.BigEndian.to!(uint)(input[4..8]); |
0 | 80 |
14
5ce3012f1def
Removed some redundancy in code. Added NotSupportedError, a base PRNG class and a class which creates a PRNG from a hash function. Changed the MAC class' finalization methods to digest and hexDigest instead of finish and hexFinish respectively. Also added a base Checksum class, crc32 and adler32 in dcrypt.misc as per request.
Thomas Dixon <reikon@reikon.us>
parents:
12
diff
changeset
|
81 if (_encrypt) { |
0 | 82 for (int i = 0; i < ROUNDS; i++) { |
83 v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ sum0[i]; | |
84 v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ sum1[i]; | |
85 } | |
86 } else { | |
87 for (int i = ROUNDS-1; i >= 0; i--) { | |
88 v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ sum1[i]; | |
89 v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ sum0[i]; | |
90 } | |
91 } | |
92 | |
23
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
93 output[0..4] = ByteConverter.BigEndian.from!(uint)(v0); |
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
94 output[4..8] = ByteConverter.BigEndian.from!(uint)(v1); |
0 | 95 |
12
8c7f8fecdd75
Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents:
8
diff
changeset
|
96 return BLOCK_SIZE; |
0 | 97 } |
98 | |
99 /** Some XTEA test vectors. */ | |
100 version (UnitTest) { | |
101 unittest { | |
102 static const char[][] test_keys = [ | |
103 "00000000000000000000000000000000", | |
104 "00000000000000000000000000000000", | |
105 "0123456712345678234567893456789a", | |
106 "0123456712345678234567893456789a", | |
107 "00000000000000000000000000000001", | |
108 "01010101010101010101010101010101", | |
109 "0123456789abcdef0123456789abcdef", | |
110 "0123456789abcdef0123456789abcdef", | |
111 "00000000000000000000000000000000", | |
112 "00000000000000000000000000000000" | |
113 ]; | |
114 | |
115 static const char[][] test_plaintexts = [ | |
116 "0000000000000000", | |
117 "0102030405060708", | |
118 "0000000000000000", | |
119 "0102030405060708", | |
120 "0000000000000001", | |
121 "0101010101010101", | |
122 "0123456789abcdef", | |
123 "0000000000000000", | |
124 "0123456789abcdef", | |
125 "4141414141414141" | |
126 ]; | |
127 | |
128 static const char[][] test_ciphertexts = [ | |
129 "dee9d4d8f7131ed9", | |
130 "065c1b8975c6a816", | |
131 "1ff9a0261ac64264", | |
132 "8c67155b2ef91ead", | |
133 "9f25fa5b0f86b758", | |
134 "c2eca7cec9b7f992", | |
135 "27e795e076b2b537", | |
136 "5c8eddc60a95b3e1", | |
137 "7e66c71c88897221", | |
138 "ed23375a821a8c2d" | |
139 ]; | |
140 | |
141 XTEA t = new XTEA(); | |
142 foreach (uint i, char[] test_key; test_keys) { | |
143 ubyte[] buffer = new ubyte[t.blockSize]; | |
144 char[] result; | |
23
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
145 SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_key)); |
0 | 146 |
147 // Encryption | |
148 t.init(true, key); | |
23
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
149 t.update(ByteConverter.hexDecode(test_plaintexts[i]), buffer); |
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
150 result = ByteConverter.hexEncode(buffer); |
0 | 151 assert(result == test_ciphertexts[i], |
2
71aae178f89a
Added copy() to hash functions. Modified some code style.
Thomas Dixon <reikon@reikon.us>
parents:
1
diff
changeset
|
152 t.name~": ("~result~") != ("~test_ciphertexts[i]~")"); |
0 | 153 |
154 // Decryption | |
155 t.init(false, key); | |
23
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
156 t.update(ByteConverter.hexDecode(test_ciphertexts[i]), buffer); |
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
157 result = ByteConverter.hexEncode(buffer); |
0 | 158 assert(result == test_plaintexts[i], |
6
5cb17e09d685
Minor edits to the unittests of hash functions and ciphers. Added AES and test vectors.
Thomas Dixon <reikon@reikon.us>
parents:
2
diff
changeset
|
159 t.name~": ("~result~") != ("~test_plaintexts[i]~")"); |
0 | 160 } |
161 } | |
162 } | |
163 } |