comparison dcrypt/crypto/ciphers/ChaCha.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 176c933827a8
children ad687db713a4
comparison
equal deleted inserted replaced
26:176c933827a8 27:8b5eaf3c2979
13 import dcrypt.crypto.params.ParametersWithIV; 13 import dcrypt.crypto.params.ParametersWithIV;
14 import dcrypt.misc.ByteConverter; 14 import dcrypt.misc.ByteConverter;
15 import dcrypt.misc.Bitwise; 15 import dcrypt.misc.Bitwise;
16 16
17 /** Implementation of ChaCha designed by Daniel J. Bernstein. */ 17 /** Implementation of ChaCha designed by Daniel J. Bernstein. */
18 class ChaCha : Salsa20 { 18 class ChaCha : Salsa20
19 char[] name() { 19 {
20 char[] name()
21 {
20 return "ChaCha"; 22 return "ChaCha";
21 } 23 }
22 24
23 this() { 25 this()
26 {
24 i0 = 12; 27 i0 = 12;
25 i1 = 13; 28 i1 = 13;
26 } 29 }
27 30
28 protected void keySetup() { 31 protected void keySetup()
32 {
29 uint offset; 33 uint offset;
30 ubyte[] constants; 34 ubyte[] constants;
31 35
32 state[4] = ByteConverter.LittleEndian.to!(uint)(workingKey[0..4]); 36 state[4] = ByteConverter.LittleEndian.to!(uint)(workingKey[0..4]);
33 state[5] = ByteConverter.LittleEndian.to!(uint)(workingKey[4..8]); 37 state[5] = ByteConverter.LittleEndian.to!(uint)(workingKey[4..8]);
34 state[6] = ByteConverter.LittleEndian.to!(uint)(workingKey[8..12]); 38 state[6] = ByteConverter.LittleEndian.to!(uint)(workingKey[8..12]);
35 state[7] = ByteConverter.LittleEndian.to!(uint)(workingKey[12..16]); 39 state[7] = ByteConverter.LittleEndian.to!(uint)(workingKey[12..16]);
36 40
37 if (workingKey.length == 32) { 41 if (workingKey.length == 32)
42 {
38 constants = sigma; 43 constants = sigma;
39 offset = 16; 44 offset = 16;
40 } else 45 } else
41 constants = tau; 46 constants = tau;
42 47
48 state[ 1] = ByteConverter.LittleEndian.to!(uint)(constants[4..8]); 53 state[ 1] = ByteConverter.LittleEndian.to!(uint)(constants[4..8]);
49 state[ 2] = ByteConverter.LittleEndian.to!(uint)(constants[8..12]); 54 state[ 2] = ByteConverter.LittleEndian.to!(uint)(constants[8..12]);
50 state[ 3] = ByteConverter.LittleEndian.to!(uint)(constants[12..16]); 55 state[ 3] = ByteConverter.LittleEndian.to!(uint)(constants[12..16]);
51 } 56 }
52 57
53 protected void ivSetup() { 58 protected void ivSetup()
59 {
54 state[12] = state[13] = 0; 60 state[12] = state[13] = 0;
55 state[14] = ByteConverter.LittleEndian.to!(uint)(workingIV[0..4]); 61 state[14] = ByteConverter.LittleEndian.to!(uint)(workingIV[0..4]);
56 state[15] = ByteConverter.LittleEndian.to!(uint)(workingIV[4..8]); 62 state[15] = ByteConverter.LittleEndian.to!(uint)(workingIV[4..8]);
57 } 63 }
58 64
59 protected void salsa20WordToByte(uint[] input, ref ubyte[] output) { 65 protected void salsa20WordToByte(uint[] input, ref ubyte[] output)
66 {
60 uint[] x = new uint[16]; 67 uint[] x = new uint[16];
61 x[] = input; 68 x[] = input;
62 69
63 int i; 70 int i;
64 for (i = 0; i < 4; i++) { 71 for (i = 0; i < 4; i++)
72 {
65 x[ 0] += x[ 4]; x[12] = Bitwise.rotateLeft(x[12]^x[ 0], 16); 73 x[ 0] += x[ 4]; x[12] = Bitwise.rotateLeft(x[12]^x[ 0], 16);
66 x[ 8] += x[12]; x[ 4] = Bitwise.rotateLeft(x[ 4]^x[ 8], 12); 74 x[ 8] += x[12]; x[ 4] = Bitwise.rotateLeft(x[ 4]^x[ 8], 12);
67 x[ 0] += x[ 4]; x[12] = Bitwise.rotateLeft(x[12]^x[ 0], 8); 75 x[ 0] += x[ 4]; x[12] = Bitwise.rotateLeft(x[12]^x[ 0], 8);
68 x[ 8] += x[12]; x[ 4] = Bitwise.rotateLeft(x[ 4]^x[ 8], 7); 76 x[ 8] += x[12]; x[ 4] = Bitwise.rotateLeft(x[ 4]^x[ 8], 7);
69 x[ 1] += x[ 5]; x[13] = Bitwise.rotateLeft(x[13]^x[ 1], 16); 77 x[ 1] += x[ 5]; x[13] = Bitwise.rotateLeft(x[13]^x[ 1], 16);
103 for (i = j = 0; i < x.length; i++,j+=int.sizeof) 111 for (i = j = 0; i < x.length; i++,j+=int.sizeof)
104 output[j..j+int.sizeof] = ByteConverter.LittleEndian.from!(uint)(x[i]); 112 output[j..j+int.sizeof] = ByteConverter.LittleEndian.from!(uint)(x[i]);
105 } 113 }
106 114
107 /** ChaCha test vectors */ 115 /** ChaCha test vectors */
108 debug (UnitTest) { 116 debug (UnitTest)
109 unittest { 117 {
118 unittest
119 {
110 static const char[][] test_keys = [ 120 static const char[][] test_keys = [
111 "80000000000000000000000000000000", 121 "80000000000000000000000000000000",
112 "0053a6f94c9ff24598eb3e91e4378add", 122 "0053a6f94c9ff24598eb3e91e4378add",
113 "00002000000000000000000000000000"~ 123 "00002000000000000000000000000000"~
114 "00000000000000000000000000000000", 124 "00000000000000000000000000000000",
171 ]; 181 ];
172 182
173 ChaCha cc = new ChaCha(); 183 ChaCha cc = new ChaCha();
174 ubyte[] buffer = new ubyte[64]; 184 ubyte[] buffer = new ubyte[64];
175 char[] result; 185 char[] result;
176 for (int i = 0; i < test_keys.length; i++) { 186 for (int i = 0; i < test_keys.length; i++)
187 {
177 SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_keys[i])); 188 SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_keys[i]));
178 ParametersWithIV params = new ParametersWithIV(key, ByteConverter.hexDecode(test_ivs[i])); 189 ParametersWithIV params = new ParametersWithIV(key, ByteConverter.hexDecode(test_ivs[i]));
179 190
180 // Encryption 191 // Encryption
181 cc.init(true, params); 192 cc.init(true, params);