comparison dcrypt/crypto/hashes/SHA1.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
15 * 15 *
16 * Conforms: FIPS 180-1 16 * Conforms: FIPS 180-1
17 * References: http://www.itl.nist.gov/fipspubs/fip180-1.htm 17 * References: http://www.itl.nist.gov/fipspubs/fip180-1.htm
18 * Bugs: SHA-1 is not cryptographically secure. 18 * Bugs: SHA-1 is not cryptographically secure.
19 */ 19 */
20 class SHA1 : Hash { 20 class SHA1 : Hash
21 {
21 protected uint h0, h1, h2, h3, h4; 22 protected uint h0, h1, h2, h3, h4;
22 23
23 this (void[] input_=null) { 24 this (void[] input_=null)
25 {
24 reset(); 26 reset();
25 super(input_); 27 super(input_);
26 } 28 }
27 29
28 uint blockSize() { 30 uint blockSize()
31 {
29 return 64; 32 return 64;
30 } 33 }
31 34
32 uint digestSize() { 35 uint digestSize()
36 {
33 return 20; 37 return 20;
34 } 38 }
35 39
36 char[] name() { 40 char[] name()
41 {
37 return "SHA1"; 42 return "SHA1";
38 } 43 }
39 44
40 void transform(ubyte[] input) { 45 void transform(ubyte[] input)
46 {
41 uint[] w = new uint[80]; 47 uint[] w = new uint[80];
42 48
43 for (int i = 0, j = 0; i < 16; i++,j+=int.sizeof) 49 for (int i = 0, j = 0; i < 16; i++,j+=int.sizeof)
44 w[i] = ByteConverter.BigEndian.to!(uint)(input[j..j+int.sizeof]); 50 w[i] = ByteConverter.BigEndian.to!(uint)(input[j..j+int.sizeof]);
45 51
51 c = h2, 57 c = h2,
52 d = h3, 58 d = h3,
53 e = h4; 59 e = h4;
54 60
55 int i = 0; 61 int i = 0;
56 for (; i < 20;) { 62 for (; i < 20;)
63 {
57 e += Bitwise.rotateLeft(a, 5) + f0(b, c, d) + w[i++]; 64 e += Bitwise.rotateLeft(a, 5) + f0(b, c, d) + w[i++];
58 b = Bitwise.rotateLeft(b, 30); 65 b = Bitwise.rotateLeft(b, 30);
59 66
60 d += Bitwise.rotateLeft(e, 5) + f0(a, b, c) + w[i++]; 67 d += Bitwise.rotateLeft(e, 5) + f0(a, b, c) + w[i++];
61 a = Bitwise.rotateLeft(a, 30); 68 a = Bitwise.rotateLeft(a, 30);
68 75
69 a += Bitwise.rotateLeft(b, 5) + f0(c, d, e) + w[i++]; 76 a += Bitwise.rotateLeft(b, 5) + f0(c, d, e) + w[i++];
70 c = Bitwise.rotateLeft(c, 30); 77 c = Bitwise.rotateLeft(c, 30);
71 } 78 }
72 79
73 for (; i < 40;) { 80 for (; i < 40;)
81 {
74 e += Bitwise.rotateLeft(a, 5) + f1(b, c, d) + w[i++]; 82 e += Bitwise.rotateLeft(a, 5) + f1(b, c, d) + w[i++];
75 b = Bitwise.rotateLeft(b, 30); 83 b = Bitwise.rotateLeft(b, 30);
76 84
77 d += Bitwise.rotateLeft(e, 5) + f1(a, b, c) + w[i++]; 85 d += Bitwise.rotateLeft(e, 5) + f1(a, b, c) + w[i++];
78 a = Bitwise.rotateLeft(a, 30); 86 a = Bitwise.rotateLeft(a, 30);
85 93
86 a += Bitwise.rotateLeft(b, 5) + f1(c, d, e) + w[i++]; 94 a += Bitwise.rotateLeft(b, 5) + f1(c, d, e) + w[i++];
87 c = Bitwise.rotateLeft(c, 30); 95 c = Bitwise.rotateLeft(c, 30);
88 } 96 }
89 97
90 for (; i < 60;) { 98 for (; i < 60;)
99 {
91 e += Bitwise.rotateLeft(a, 5) + f2(b, c, d) + w[i++]; 100 e += Bitwise.rotateLeft(a, 5) + f2(b, c, d) + w[i++];
92 b = Bitwise.rotateLeft(b, 30); 101 b = Bitwise.rotateLeft(b, 30);
93 102
94 d += Bitwise.rotateLeft(e, 5) + f2(a, b, c) + w[i++]; 103 d += Bitwise.rotateLeft(e, 5) + f2(a, b, c) + w[i++];
95 a = Bitwise.rotateLeft(a, 30); 104 a = Bitwise.rotateLeft(a, 30);
102 111
103 a += Bitwise.rotateLeft(b, 5) + f2(c, d, e) + w[i++]; 112 a += Bitwise.rotateLeft(b, 5) + f2(c, d, e) + w[i++];
104 c = Bitwise.rotateLeft(c, 30); 113 c = Bitwise.rotateLeft(c, 30);
105 } 114 }
106 115
107 for (; i < 80;) { 116 for (; i < 80;)
117 {
108 e += Bitwise.rotateLeft(a, 5) + f3(b, c, d) + w[i++]; 118 e += Bitwise.rotateLeft(a, 5) + f3(b, c, d) + w[i++];
109 b = Bitwise.rotateLeft(b, 30); 119 b = Bitwise.rotateLeft(b, 30);
110 120
111 d += Bitwise.rotateLeft(e, 5) + f3(a, b, c) + w[i++]; 121 d += Bitwise.rotateLeft(e, 5) + f3(a, b, c) + w[i++];
112 a = Bitwise.rotateLeft(a, 30); 122 a = Bitwise.rotateLeft(a, 30);
126 h2 += c; 136 h2 += c;
127 h3 += d; 137 h3 += d;
128 h4 += e; 138 h4 += e;
129 } 139 }
130 140
131 private uint f0(uint x, uint y, uint z) { 141 private uint f0(uint x, uint y, uint z)
142 {
132 return (z^(x&(y^z))) + 0x5a827999; 143 return (z^(x&(y^z))) + 0x5a827999;
133 } 144 }
134 145
135 private uint f1(uint x, uint y, uint z) { 146 private uint f1(uint x, uint y, uint z)
147 {
136 return (x^y^z) + 0x6ed9eba1; 148 return (x^y^z) + 0x6ed9eba1;
137 } 149 }
138 150
139 private uint f2(uint x, uint y, uint z) { 151 private uint f2(uint x, uint y, uint z)
152 {
140 return ((x&y)|(z&(x|y))) + 0x8f1bbcdc; 153 return ((x&y)|(z&(x|y))) + 0x8f1bbcdc;
141 } 154 }
142 155
143 private uint f3(uint x, uint y, uint z) { 156 private uint f3(uint x, uint y, uint z)
157 {
144 return (x^y^z) + 0xca62c1d6; 158 return (x^y^z) + 0xca62c1d6;
145 } 159 }
146 160
147 ubyte[] digest() { 161 ubyte[] digest()
162 {
148 padMessage(MODE_SHA); 163 padMessage(MODE_SHA);
149 ubyte[] result = new ubyte[digestSize]; 164 ubyte[] result = new ubyte[digestSize];
150 165
151 result[0..4] = ByteConverter.BigEndian.from!(uint)(h0); 166 result[0..4] = ByteConverter.BigEndian.from!(uint)(h0);
152 result[4..8] = ByteConverter.BigEndian.from!(uint)(h1); 167 result[4..8] = ByteConverter.BigEndian.from!(uint)(h1);
156 171
157 reset(); 172 reset();
158 return result; 173 return result;
159 } 174 }
160 175
161 void reset() { 176 void reset()
177 {
162 super.reset(); 178 super.reset();
163 h0 = 0x67452301u; 179 h0 = 0x67452301u;
164 h1 = 0xefcdab89u; 180 h1 = 0xefcdab89u;
165 h2 = 0x98badcfeu; 181 h2 = 0x98badcfeu;
166 h3 = 0x10325476u; 182 h3 = 0x10325476u;
167 h4 = 0xc3d2e1f0u; 183 h4 = 0xc3d2e1f0u;
168 } 184 }
169 185
170 SHA1 copy() { 186 SHA1 copy()
187 {
171 SHA1 h = new SHA1(buffer[0..index]); 188 SHA1 h = new SHA1(buffer[0..index]);
172 h.bytes = bytes; 189 h.bytes = bytes;
173 h.h0 = h0; 190 h.h0 = h0;
174 h.h1 = h1; 191 h.h1 = h1;
175 h.h2 = h2; 192 h.h2 = h2;
176 h.h3 = h3; 193 h.h3 = h3;
177 h.h4 = h4; 194 h.h4 = h4;
178 return h; 195 return h;
179 } 196 }
180 197
181 debug (UnitTest) { 198 debug (UnitTest)
182 unittest { 199 {
200 unittest
201 {
183 static const char[][] test_inputs = [ 202 static const char[][] test_inputs = [
184 "", 203 "",
185 "abc", 204 "abc",
186 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 205 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
187 "a", 206 "a",
199 "34aa973cd4c4daa4f61eeb2bdbad27316534016f", 218 "34aa973cd4c4daa4f61eeb2bdbad27316534016f",
200 "dea356a2cddd90c7a7ecedc5ebb563934f460452" 219 "dea356a2cddd90c7a7ecedc5ebb563934f460452"
201 ]; 220 ];
202 221
203 SHA1 h = new SHA1(); 222 SHA1 h = new SHA1();
204 foreach (uint i, char[] input; test_inputs) { 223 foreach (uint i, char[] input; test_inputs)
224 {
205 for (int j = 0; j < test_repeat[i]; j++) 225 for (int j = 0; j < test_repeat[i]; j++)
206 h.update(input); 226 h.update(input);
207 char[] digest = h.hexDigest(); 227 char[] digest = h.hexDigest();
208 assert(digest == test_results[i], 228 assert(digest == test_results[i],
209 h.name~": ("~digest~") != ("~test_results[i]~")"); 229 h.name~": ("~digest~") != ("~test_results[i]~")");