Mercurial > projects > dcrypt
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); |