~lovesyao/+junk/transgs

« back to all changes in this revision

Viewing changes to nazo/md5.d

  • Committer: Nazo
  • Date: 2008-10-18 08:26:14 UTC
  • Revision ID: lovesyao@hotmail.com-20081018082614-22qgtg2gsotz5r2i
initial checkin

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
module nazo.md5;
 
2
/**
 
3
 * FastMd5 based on std.md5
 
4
 */
 
5
 
 
6
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
 
7
rights reserved.
 
8
 
 
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
 
12
or this function.
 
13
 
 
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.
 
18
 
 
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.
 
25
 */
 
26
 
 
27
import std.string, nazo.mem, std.stdio;
 
28
 
 
29
/***************************************
 
30
 * Computes MD5 digest of array of data.
 
31
 */
 
32
 
 
33
void sum(ubyte[16] digest, void[] data)
 
34
{
 
35
    MD5_CTX context;
 
36
    context.sum(cast(ubyte[])data, digest);
 
37
}
 
38
 
 
39
/******************
 
40
 * Prints a message digest in hexadecimal to stdout.
 
41
 */
 
42
void printDigest(ubyte digest[16])
 
43
{
 
44
    foreach (ubyte u; digest)
 
45
        printf("%02x", u);
 
46
}
 
47
 
 
48
/****************************************
 
49
 * Converts MD5 digest to a string.
 
50
 */
 
51
 
 
52
char[] digestToString(ubyte[16] digest)
 
53
{
 
54
    char[] result = new char[32];
 
55
    int i;
 
56
 
 
57
    foreach (inout ubyte u; digest)
 
58
    {
 
59
        result[i++] = std.string.hexdigits[u >> 4];
 
60
        result[i++] = std.string.hexdigits[u & 15];
 
61
    }
 
62
    return result;
 
63
}
 
64
 
 
65
/**
 
66
 * Holds context of MD5 computation.
 
67
 *
 
68
 * Used when data to be digested is buffered.
 
69
 */
 
70
struct MD5_CTX
 
71
{
 
72
    const static uint state[4] =                                   /* state (ABCD) */
 
73
    /* magic initialization constants */
 
74
    [0x67452301,0xefcdab89,0x98badcfe,0x10325476];
 
75
 
 
76
    /* F, G, H and I are basic MD5 functions.
 
77
     */
 
78
    private static
 
79
    {
 
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); }
 
84
    }
 
85
 
 
86
    /* ROTATE_LEFT rotates x left n bits.
 
87
     */
 
88
    static uint ROTATE_LEFT(uint x, uint n)
 
89
    {
 
90
        version (X86)
 
91
        {
 
92
            asm
 
93
            {   naked                        ;
 
94
                mov        ECX,EAX                ;
 
95
                mov        EAX,4[ESP]        ;
 
96
                rol        EAX,CL                ;
 
97
                ret        4                ;
 
98
            }
 
99
        }
 
100
        else
 
101
        {
 
102
            return (x << n) | (x >> (32-n));
 
103
        }
 
104
    }
 
105
 
 
106
    /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
 
107
     * Rotation is separate from addition to prevent recomputation.
 
108
     */
 
109
    static void FF(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
 
110
    {
 
111
        a += F (b, c, d) + x + cast(uint)(ac);
 
112
        a = ROTATE_LEFT (a, s);
 
113
        a += b;
 
114
    }
 
115
 
 
116
    static void GG(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
 
117
    {
 
118
        a += G (b, c, d) + x + cast(uint)(ac);
 
119
        a = ROTATE_LEFT (a, s);
 
120
        a += b;
 
121
    }
 
122
 
 
123
    static void HH(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
 
124
    {
 
125
        a += H (b, c, d) + x + cast(uint)(ac);
 
126
        a = ROTATE_LEFT (a, s);
 
127
        a += b;
 
128
    }
 
129
 
 
130
    static void II(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
 
131
    {
 
132
        a += I (b, c, d) + x + cast(uint)(ac);
 
133
        a = ROTATE_LEFT (a, s);
 
134
        a += b;
 
135
    }
 
136
 
 
137
    void sum(ubyte[] input, ubyte[16] digest)
 
138
    {
 
139
      ubyte[64] last;
 
140
      memcpy!(16)(digest.ptr, state.ptr);
 
141
 
 
142
      ulong count = input.length << 3;//*8
 
143
      int cur=input.length & 0b111111;//%64
 
144
      if(cur!=0){
 
145
        last[0..cur] = input[$-cur..$];
 
146
        input.length=input.length - cur;
 
147
      }
 
148
      last[cur++]=0x80;
 
149
      uint[] tmp_digest = cast(uint[])digest;
 
150
 
 
151
      for (uint i = 0; i < input.length; i += 64)
 
152
        transform (cast(uint*)(input.ptr+i), tmp_digest);
 
153
 
 
154
      if(cur+8 > 64){
 
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);
 
159
      }else{
 
160
        memcpy!(8)(last.ptr+64-8 ,&count);
 
161
        transform (cast(uint*)last.ptr, tmp_digest);
 
162
      }
 
163
    }
 
164
 
 
165
 
 
166
    /* MD5 basic transformation. Transforms state based on block.
 
167
     */
 
168
 
 
169
    /* Constants for MD5Transform routine. */
 
170
    enum
 
171
    {
 
172
        S11 = 7,
 
173
        S12 = 12,
 
174
        S13 = 17,
 
175
        S14 = 22,
 
176
        S21 = 5,
 
177
        S22 = 9,
 
178
        S23 = 14,
 
179
        S24 = 20,
 
180
        S31 = 4,
 
181
        S32 = 11,
 
182
        S33 = 16,
 
183
        S34 = 23,
 
184
        S41 = 6,
 
185
        S42 = 10,
 
186
        S43 = 15,
 
187
        S44 = 21,
 
188
    }
 
189
 
 
190
    private static void transform (uint* x, uint[] digest)
 
191
    {
 
192
      uint a = digest[0],
 
193
           b = digest[1],
 
194
           c = digest[2],
 
195
           d = digest[3];
 
196
 
 
197
      /* Round 1 */
 
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 */
 
214
 
 
215
     /* Round 2 */
 
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 */
 
232
 
 
233
      /* Round 3 */
 
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 */
 
250
 
 
251
      /* Round 4 */
 
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 */
 
268
 
 
269
      digest[0] += a;
 
270
      digest[1] += b;
 
271
      digest[2] += c;
 
272
      digest[3] += d;
 
273
    }
 
274
}
 
275
 
 
276
unittest
 
277
{
 
278
    debug(md5) printf("std.md5.unittest\n");
 
279
 
 
280
    ubyte[16] digest;
 
281
 
 
282
    sum (digest, "");
 
283
    assert(digest == cast(ubyte[])x"d41d8cd98f00b204e9800998ecf8427e");
 
284
 
 
285
    sum (digest, "a");
 
286
    assert(digest == cast(ubyte[])x"0cc175b9c0f1b6a831c399e269772661");
 
287
 
 
288
    sum (digest, "abc");
 
289
    assert(digest == cast(ubyte[])x"900150983cd24fb0d6963f7d28e17f72");
 
290
 
 
291
    sum (digest, "message digest");
 
292
    assert(digest == cast(ubyte[])x"f96b697d7cb7938d525a2f31aaf161d0");
 
293
 
 
294
    sum (digest, "abcdefghijklmnopqrstuvwxyz");
 
295
    assert(digest == cast(ubyte[])x"c3fcd3d76192e4007dfb496cca67e13b");
 
296
 
 
297
    sum (digest, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
 
298
    assert(digest == cast(ubyte[])x"d174ab98d277d9f5a5611c2c9f419d9f");
 
299
 
 
300
    sum (digest,
 
301
        "1234567890123456789012345678901234567890"
 
302
        "1234567890123456789012345678901234567890");
 
303
    assert(digest == cast(ubyte[])x"57edf4a22be3c955ac49da2e2107b67a");
 
304
 
 
305
    assert(digestToString(cast(ubyte[16])x"c3fcd3d76192e4007dfb496cca67e13b")
 
306
        == "C3FCD3D76192E4007DFB496CCA67E13B");
 
307
}
 
308