3
* FastMd5 based on std.md5
6
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
9
License to copy and use this software is granted provided that it
10
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
11
Algorithm" in all material mentioning or referencing this software
14
License is also granted to make and use derivative works provided
15
that such works are identified as "derived from the RSA Data
16
Security, Inc. MD5 Message-Digest Algorithm" in all material
17
mentioning or referencing the derived work.
19
RSA Data Security, Inc. makes no representations concerning either
20
the merchantability of this software or the suitability of this
21
software for any particular purpose. It is provided "as is"
22
without express or implied warranty of any kind.
23
These notices must be retained in any copies of any part of this
24
documentation and/or software.
27
import std.string, nazo.mem, std.stdio;
29
/***************************************
30
* Computes MD5 digest of array of data.
33
void sum(ubyte[16] digest, void[] data)
36
context.sum(cast(ubyte[])data, digest);
40
* Prints a message digest in hexadecimal to stdout.
42
void printDigest(ubyte digest[16])
44
foreach (ubyte u; digest)
48
/****************************************
49
* Converts MD5 digest to a string.
52
char[] digestToString(ubyte[16] digest)
54
char[] result = new char[32];
57
foreach (inout ubyte u; digest)
59
result[i++] = std.string.hexdigits[u >> 4];
60
result[i++] = std.string.hexdigits[u & 15];
66
* Holds context of MD5 computation.
68
* Used when data to be digested is buffered.
72
const static uint state[4] = /* state (ABCD) */
73
/* magic initialization constants */
74
[0x67452301,0xefcdab89,0x98badcfe,0x10325476];
76
/* F, G, H and I are basic MD5 functions.
80
uint F(uint x, uint y, uint z) { return (x & y) | (~x & z); }
81
uint G(uint x, uint y, uint z) { return (x & z) | (y & ~z); }
82
uint H(uint x, uint y, uint z) { return x ^ y ^ z; }
83
uint I(uint x, uint y, uint z) { return y ^ (x | ~z); }
86
/* ROTATE_LEFT rotates x left n bits.
88
static uint ROTATE_LEFT(uint x, uint n)
102
return (x << n) | (x >> (32-n));
106
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
107
* Rotation is separate from addition to prevent recomputation.
109
static void FF(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
111
a += F (b, c, d) + x + cast(uint)(ac);
112
a = ROTATE_LEFT (a, s);
116
static void GG(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
118
a += G (b, c, d) + x + cast(uint)(ac);
119
a = ROTATE_LEFT (a, s);
123
static void HH(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
125
a += H (b, c, d) + x + cast(uint)(ac);
126
a = ROTATE_LEFT (a, s);
130
static void II(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
132
a += I (b, c, d) + x + cast(uint)(ac);
133
a = ROTATE_LEFT (a, s);
137
void sum(ubyte[] input, ubyte[16] digest)
140
memcpy!(16)(digest.ptr, state.ptr);
142
ulong count = input.length << 3;//*8
143
int cur=input.length & 0b111111;//%64
145
last[0..cur] = input[$-cur..$];
146
input.length=input.length - cur;
149
uint[] tmp_digest = cast(uint[])digest;
151
for (uint i = 0; i < input.length; i += 64)
152
transform (cast(uint*)(input.ptr+i), tmp_digest);
155
transform (cast(uint*)last.ptr, tmp_digest);
156
memzero!(64-8)(last.ptr);
157
memcpy!(8)(last.ptr+64-8 ,&count);
158
transform (cast(uint*)last.ptr, tmp_digest);
160
memcpy!(8)(last.ptr+64-8 ,&count);
161
transform (cast(uint*)last.ptr, tmp_digest);
166
/* MD5 basic transformation. Transforms state based on block.
169
/* Constants for MD5Transform routine. */
190
private static void transform (uint* x, uint[] digest)
198
FF (a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
199
FF (d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
200
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
201
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
202
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
203
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
204
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
205
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
206
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
207
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
208
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
209
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
210
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
211
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
212
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
213
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
216
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
217
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
218
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
219
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
220
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
221
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
222
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
223
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
224
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
225
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
226
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
227
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
228
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
229
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
230
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
231
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
234
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
235
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
236
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
237
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
238
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
239
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
240
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
241
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
242
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
243
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
244
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
245
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
246
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
247
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
248
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
249
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
252
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
253
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
254
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
255
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
256
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
257
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
258
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
259
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
260
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
261
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
262
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
263
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
264
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
265
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
266
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
267
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
278
debug(md5) printf("std.md5.unittest\n");
283
assert(digest == cast(ubyte[])x"d41d8cd98f00b204e9800998ecf8427e");
286
assert(digest == cast(ubyte[])x"0cc175b9c0f1b6a831c399e269772661");
289
assert(digest == cast(ubyte[])x"900150983cd24fb0d6963f7d28e17f72");
291
sum (digest, "message digest");
292
assert(digest == cast(ubyte[])x"f96b697d7cb7938d525a2f31aaf161d0");
294
sum (digest, "abcdefghijklmnopqrstuvwxyz");
295
assert(digest == cast(ubyte[])x"c3fcd3d76192e4007dfb496cca67e13b");
297
sum (digest, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
298
assert(digest == cast(ubyte[])x"d174ab98d277d9f5a5611c2c9f419d9f");
301
"1234567890123456789012345678901234567890"
302
"1234567890123456789012345678901234567890");
303
assert(digest == cast(ubyte[])x"57edf4a22be3c955ac49da2e2107b67a");
305
assert(digestToString(cast(ubyte[16])x"c3fcd3d76192e4007dfb496cca67e13b")
306
== "C3FCD3D76192E4007DFB496CCA67E13B");