Thread overview
MD5 does not work
Apr 14, 2005
k2
Apr 14, 2005
Regan Heath
Apr 14, 2005
k2
Apr 14, 2005
Regan Heath
Apr 14, 2005
Regan Heath
Apr 14, 2005
Ben Hinkle
Apr 15, 2005
jicman
Apr 15, 2005
k2
Apr 15, 2005
Walter
April 14, 2005
MD5.finish always return 0.

---
win32 DMD 0.120


April 14, 2005
On Thu, 14 Apr 2005 07:04:04 +0000 (UTC), k2 <k2_member@pathlink.com> wrote:
> MD5.finish always return 0.
>
> ---
> win32 DMD 0.120

std.md5? MD5_CTX.finish returns "void"? Can you post an example?

Regan
April 14, 2005
Sorry, I can not speak English.
This sample code is here:
http://www.digitalmars.com/d/phobos.html#md5

---
// test_md5.d
import std.md5;
import std.string;
import std.c.stdio;

int main(char[][] args)
{
for (int i = 1; i < args.length; i++)
MDFile(args[i]);
return 0;
}

/* Digests a file and prints the result. */
void MDFile(char[] filename)
{
FILE* file;
MD5_CTX context;
int len;
ubyte [4 * 1024] buffer;
ubyte digest[16];

if ((file = fopen(std.string.toStringz(filename), "rb")) == null)
printf("%.*s can't be opened\n", filename);
else
{
context.start();
while ((len = fread(buffer, 1, buffer.sizeof, file)) != 0)
context.update(buffer[0 .. len]);
context.finish(digest);
fclose(file);

printf("MD5 (%.*s) = ", filename);
printDigest(digest);
printf("\n");
}
}

---
>dmd test_md5.d
>test_md5 test_md5.d
MD5 (test_md5.d) = 00000000000000000000000000000000



April 14, 2005
On Thu, 14 Apr 2005 11:16:11 +0000 (UTC), k2 <k2_member@pathlink.com> wrote:
> Sorry, I can not speak English.

No problem. You're doing a pretty good job so far.

> This sample code is here:
> http://www.digitalmars.com/d/phobos.html#md5

Thanks. It appears to be a bug in DMD, I think, the parameter to 'finish' is getting data assigned but it then vanishes, further, trying to access "digest" during "finish" causes an access violation.

Here is what I did. I took the contents of std.md5 and pasted it into the sample code instead of importing it so I could add debugging printfs.

import std.c.stdio;
import std.string;
import std.stdio;

/* MD5 context. */
struct MD5_CTX
{
    uint state[4] =                                   /* state (ABCD) */
    /* magic initialization constants */
    [0x67452301,0xefcdab89,0x98badcfe,0x10325476];

    ulong count;	/* number of bits, modulo 2^64 */
    ubyte buffer[64];	/* input buffer */

    static ubyte[64] PADDING =
    [
      0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    ];

    /* F, G, H and I are basic MD5 functions.
     */
    private static
    {
	uint F(uint x, uint y, uint z) { return (x & y) | (~x & z); }
	uint G(uint x, uint y, uint z) { return (x & z) | (y & ~z); }
	uint H(uint x, uint y, uint z) { return x ^ y ^ z; }
	uint I(uint x, uint y, uint z) { return y ^ (x | ~z); }
    }

    /* ROTATE_LEFT rotates x left n bits.
     */
    static uint ROTATE_LEFT(uint x, uint n)
    {
	version (X86)
	{
	    asm
	    {   naked			;
		mov	ECX,EAX		;
		mov	EAX,4[ESP]	;
		rol	EAX,CL		;
		ret	4		;
	    }
	}
	else
	{
	    return (x << n) | (x >> (32-n));
	}
    }

    /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
     * Rotation is separate from addition to prevent recomputation.
     */
    static void FF(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
    {
	a += F (b, c, d) + x + cast(uint)(ac);
	a = ROTATE_LEFT (a, s);
	a += b;
    }

    static void GG(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
    {
	a += G (b, c, d) + x + cast(uint)(ac);
	a = ROTATE_LEFT (a, s);
	a += b;
    }

    static void HH(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
    {
	a += H (b, c, d) + x + cast(uint)(ac);
	a = ROTATE_LEFT (a, s);
	a += b;
    }

    static void II(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
    {
	a += I (b, c, d) + x + cast(uint)(ac);
	a = ROTATE_LEFT (a, s);
	a += b;
    }

    /* MD5 initialization. Begins an MD5 operation, writing a new context.
     */
    void start()
    {
	*this = MD5_CTX.init;
    }

    /* MD5 block update operation. Continues an MD5 message-digest
      operation, processing another message block, and updating the
      context.
     */
    void update(void[] input)
    {
      uint i, index, partLen;
      uint inputLen = input.length;

      /* Compute number of bytes mod 64 */
      index = (cast(uint)count >> 3) & (64 - 1);

      /* Update number of bits */
      count += inputLen * 8;

      partLen = 64 - index;

      /* Transform as many times as possible. */
      if (inputLen >= partLen)
      {
	    memcpy(&buffer[index], input, partLen);
	    transform (buffer);

	    for (i = partLen; i + 63 < inputLen; i += 64)
	       transform ((cast(ubyte[])input)[i .. i + 64]);

	    index = 0;
      }
      else
	    i = 0;

      /* Buffer remaining input */
      if (inputLen - i)
	    memcpy(&buffer[index], &input[i], inputLen-i);
    }

    /* MD5 finalization. Ends an MD5 message-digest operation, writing the
     * the message digest and zeroizing the context.
     */
    void finish(ubyte[16] digest)         /* message digest */
    {
      ubyte bits[8];
      uint index, padLen;
      uint[2] cnt;

      /* Save number of bits */
      cnt[0] = cast(uint)count;
      cnt[1] = cast(uint)(count >> 32);
      Encode (bits, cnt, 8);

      /* Pad out to 56 mod 64. */
      index = (cast(uint)count >> 3) & (64 - 1);
      padLen = (index < 56) ? (56 - index) : (120 - index);
      update (PADDING[0 .. padLen]);

      /* Append length (before padding) */
      update (bits);

      /* Store state in digest */
      Encode (digest, state, 16);
      //this line causes an Error: Access Violation
      //for(int i = 0; i < 16; i++) printf("%d,",digest[i]); printf("\n");
      //have to access it this way
      {
      	ubyte *pp = digest.ptr;
      	printf("DURING: "); for(int i = 0; i < 16; i++, pp++) printf("%03d,",*pp); printf("\n");
      }

      /* Zeroize sensitive information. */
      memset (this, 0, MD5_CTX.sizeof);
    }

    /* MD5 basic transformation. Transforms state based on block.
     */

    /* Constants for MD5Transform routine. */
    enum
    {
	S11 = 7,
	S12 = 12,
	S13 = 17,
	S14 = 22,
	S21 = 5,
	S22 = 9,
	S23 = 14,
	S24 = 20,
	S31 = 4,
	S32 = 11,
	S33 = 16,
	S34 = 23,
	S41 = 6,
	S42 = 10,
	S43 = 15,
	S44 = 21,
    }

    private void transform (ubyte* /*[64]*/ block)
    {
      uint a = state[0],
	   b = state[1],
	   c = state[2],
	   d = state[3];
      uint[16] x;

      Decode (x, block, 64);

      /* Round 1 */
      FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
      FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
      FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
      FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
      FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
      FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
      FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
      FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
      FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
      FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
      FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
      FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
      FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
      FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
      FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
      FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */

     /* Round 2 */
      GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
      GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
      GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
      GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
      GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
      GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
      GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
      GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
      GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
      GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
      GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
      GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
      GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
      GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
      GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
      GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */

      /* Round 3 */
      HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
      HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
      HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
      HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
      HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
      HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
      HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
      HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
      HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
      HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
      HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
      HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
      HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
      HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
      HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
      HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */

      /* Round 4 */
      II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
      II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
      II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
      II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
      II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
      II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
      II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
      II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
      II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
      II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
      II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
      II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
      II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
      II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
      II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
      II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */

      state[0] += a;
      state[1] += b;
      state[2] += c;
      state[3] += d;

      /* Zeroize sensitive information. */
      x[] = 0;
    }

    /* Encodes input (uint) into output (ubyte). Assumes len is
      a multiple of 4.
     */
    private static void Encode (ubyte *output, uint *input, uint len)
    {
	uint i, j;

	for (i = 0, j = 0; j < len; i++, j += 4)
	{
	    uint u = input[i];
	    output[j]   = cast(ubyte)(u);
	    output[j+1] = cast(ubyte)(u >> 8);
	    output[j+2] = cast(ubyte)(u >> 16);
	    output[j+3] = cast(ubyte)(u >> 24);
	}
    }

    /* Decodes input (ubyte) into output (uint). Assumes len is
      a multiple of 4.
     */
    private static void Decode (uint *output, ubyte *input, uint len)
    {
	uint i, j;

	for (i = 0, j = 0; j < len; i++, j += 4)
	{
	    version (LittleEndian)
	    {
		output[i] = *cast(uint*)&input[j];
	    }
	    else
	    {
		output[i] = (cast(uint)input[j]) | ((cast(uint)input[j+1]) << 8) |
			((cast(uint)input[j+2]) << 16) | ((cast(uint)input[j+3]) << 24);
	    }
	}
    }
}

/*************************************
 * Computes MD5 digest of array of data
 */

void sum(ubyte[16] digest, void[] data)
{
    MD5_CTX context;

    context.start();
    context.update(data);
    context.finish(digest);
}

/* Prints a message digest in hexadecimal.
 */
void printDigest(ubyte digest[16])
{
    foreach (ubyte u; digest)
	printf("%02x", u);
}

unittest
{
    debug(md5) printf("std.md5.unittest\n");

    ubyte[16] digest;

    printf("BEFORE: "); for(int i = 0; i < 16; i++) printf("%03d,",digest[i]); printf("\n");
    sum (digest, "");
    printf("AFTER:  "); for(int i = 0; i < 16; i++) printf("%03d,",digest[i]); printf("\n");
    assert(digest == cast(ubyte[])x"d41d8cd98f00b204e9800998ecf8427e");

    sum (digest, "a");
    assert(digest == cast(ubyte[])x"0cc175b9c0f1b6a831c399e269772661");

    sum (digest, "abc");
    assert(digest == cast(ubyte[])x"900150983cd24fb0d6963f7d28e17f72");

    sum (digest, "message digest");
    assert(digest == cast(ubyte[])x"f96b697d7cb7938d525a2f31aaf161d0");

    sum (digest, "abcdefghijklmnopqrstuvwxyz");
    assert(digest == cast(ubyte[])x"c3fcd3d76192e4007dfb496cca67e13b");

    sum (digest, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
    assert(digest == cast(ubyte[])x"d174ab98d277d9f5a5611c2c9f419d9f");

    sum (digest,
	"1234567890123456789012345678901234567890"
	"1234567890123456789012345678901234567890");
    assert(digest == cast(ubyte[])x"57edf4a22be3c955ac49da2e2107b67a");

}

int main(char[][] args)
{
	for (int i = 1; i < args.length; i++)
		MDFile(args[i]);
	return 0;
}

/* Digests a file and prints the result. */
void MDFile(char[] filename)
{
	FILE* file;
	MD5_CTX context;
	int len;
	ubyte [4 * 1024] buffer;
	ubyte digest[16];

	if ((file = fopen(std.string.toStringz(filename), "rb")) == null)
		printf("%.*s can't be opened\n", filename);
	else
	{
		context.start();
		while ((len = fread(buffer, 1, buffer.sizeof, file)) != 0)
			context.update(buffer[0 .. len]);
		context.finish(digest);
		fclose(file);

		printf("MD5 (%.*s) = ", filename);
		printDigest(digest);
		printf("\n");
	}
}

Regan
April 14, 2005
I forgot to mention, compile it with -unittest and the unittests fail also.

On Fri, 15 Apr 2005 00:00:53 +1200, Regan Heath <regan@netwin.co.nz> wrote:
> On Thu, 14 Apr 2005 11:16:11 +0000 (UTC), k2 <k2_member@pathlink.com> wrote:
>> Sorry, I can not speak English.
>
> No problem. You're doing a pretty good job so far.
>
>> This sample code is here:
>> http://www.digitalmars.com/d/phobos.html#md5
>
> Thanks. It appears to be a bug in DMD, I think, the parameter to 'finish' is getting data assigned but it then vanishes, further, trying to access "digest" during "finish" causes an access violation.
>
> Here is what I did. I took the contents of std.md5 and pasted it into the sample code instead of importing it so I could add debugging printfs.
>
> import std.c.stdio;
> import std.string;
> import std.stdio;
>
> /* MD5 context. */
> struct MD5_CTX
> {
>      uint state[4] =                                   /* state (ABCD) */
>      /* magic initialization constants */
>      [0x67452301,0xefcdab89,0x98badcfe,0x10325476];
>
>      ulong count;	/* number of bits, modulo 2^64 */
>      ubyte buffer[64];	/* input buffer */
>
>      static ubyte[64] PADDING =
>      [
>        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
>        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
>        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
>      ];
>
>      /* F, G, H and I are basic MD5 functions.
>       */
>      private static
>      {
> 	uint F(uint x, uint y, uint z) { return (x & y) | (~x & z); }
> 	uint G(uint x, uint y, uint z) { return (x & z) | (y & ~z); }
> 	uint H(uint x, uint y, uint z) { return x ^ y ^ z; }
> 	uint I(uint x, uint y, uint z) { return y ^ (x | ~z); }
>      }
>
>      /* ROTATE_LEFT rotates x left n bits.
>       */
>      static uint ROTATE_LEFT(uint x, uint n)
>      {
> 	version (X86)
> 	{
> 	    asm
> 	    {   naked			;
> 		mov	ECX,EAX		;
> 		mov	EAX,4[ESP]	;
> 		rol	EAX,CL		;
> 		ret	4		;
> 	    }
> 	}
> 	else
> 	{
> 	    return (x << n) | (x >> (32-n));
> 	}
>      }
>
>      /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
>       * Rotation is separate from addition to prevent recomputation.
>       */
>      static void FF(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
>      {
> 	a += F (b, c, d) + x + cast(uint)(ac);
> 	a = ROTATE_LEFT (a, s);
> 	a += b;
>      }
>
>      static void GG(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
>      {
> 	a += G (b, c, d) + x + cast(uint)(ac);
> 	a = ROTATE_LEFT (a, s);
> 	a += b;
>      }
>
>      static void HH(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
>      {
> 	a += H (b, c, d) + x + cast(uint)(ac);
> 	a = ROTATE_LEFT (a, s);
> 	a += b;
>      }
>
>      static void II(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
>      {
> 	a += I (b, c, d) + x + cast(uint)(ac);
> 	a = ROTATE_LEFT (a, s);
> 	a += b;
>      }
>
>      /* MD5 initialization. Begins an MD5 operation, writing a new context.
>       */
>      void start()
>      {
> 	*this = MD5_CTX.init;
>      }
>
>      /* MD5 block update operation. Continues an MD5 message-digest
>        operation, processing another message block, and updating the
>        context.
>       */
>      void update(void[] input)
>      {
>        uint i, index, partLen;
>        uint inputLen = input.length;
>
>        /* Compute number of bytes mod 64 */
>        index = (cast(uint)count >> 3) & (64 - 1);
>
>        /* Update number of bits */
>        count += inputLen * 8;
>
>        partLen = 64 - index;
>
>        /* Transform as many times as possible. */
>        if (inputLen >= partLen)
>        {
> 	    memcpy(&buffer[index], input, partLen);
> 	    transform (buffer);
>
> 	    for (i = partLen; i + 63 < inputLen; i += 64)
> 	       transform ((cast(ubyte[])input)[i .. i + 64]);
>
> 	    index = 0;
>        }
>        else
> 	    i = 0;
>
>        /* Buffer remaining input */
>        if (inputLen - i)
> 	    memcpy(&buffer[index], &input[i], inputLen-i);
>      }
>
>      /* MD5 finalization. Ends an MD5 message-digest operation, writing the
>       * the message digest and zeroizing the context.
>       */
>      void finish(ubyte[16] digest)         /* message digest */
>      {
>        ubyte bits[8];
>        uint index, padLen;
>        uint[2] cnt;
>
>        /* Save number of bits */
>        cnt[0] = cast(uint)count;
>        cnt[1] = cast(uint)(count >> 32);
>        Encode (bits, cnt, 8);
>
>        /* Pad out to 56 mod 64. */
>        index = (cast(uint)count >> 3) & (64 - 1);
>        padLen = (index < 56) ? (56 - index) : (120 - index);
>        update (PADDING[0 .. padLen]);
>
>        /* Append length (before padding) */
>        update (bits);
>
>        /* Store state in digest */
>        Encode (digest, state, 16);
>        //this line causes an Error: Access Violation
>        //for(int i = 0; i < 16; i++) printf("%d,",digest[i]); printf("\n");
>        //have to access it this way
>        {
>        	ubyte *pp = digest.ptr;
>        	printf("DURING: "); for(int i = 0; i < 16; i++, pp++) printf("%03d,",*pp); printf("\n");
>        }
>
>        /* Zeroize sensitive information. */
>        memset (this, 0, MD5_CTX.sizeof);
>      }
>
>      /* MD5 basic transformation. Transforms state based on block.
>       */
>
>      /* Constants for MD5Transform routine. */
>      enum
>      {
> 	S11 = 7,
> 	S12 = 12,
> 	S13 = 17,
> 	S14 = 22,
> 	S21 = 5,
> 	S22 = 9,
> 	S23 = 14,
> 	S24 = 20,
> 	S31 = 4,
> 	S32 = 11,
> 	S33 = 16,
> 	S34 = 23,
> 	S41 = 6,
> 	S42 = 10,
> 	S43 = 15,
> 	S44 = 21,
>      }
>
>      private void transform (ubyte* /*[64]*/ block)
>      {
>        uint a = state[0],
> 	   b = state[1],
> 	   c = state[2],
> 	   d = state[3];
>        uint[16] x;
>
>        Decode (x, block, 64);
>
>        /* Round 1 */
>        FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
>        FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
>        FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
>        FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
>        FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
>        FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
>        FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
>        FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
>        FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
>        FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
>        FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
>        FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
>        FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
>        FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
>        FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
>        FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
>
>       /* Round 2 */
>        GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
>        GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
>        GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
>        GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
>        GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
>        GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
>        GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
>        GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
>        GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
>        GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
>        GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
>        GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
>        GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
>        GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
>        GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
>        GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
>
>        /* Round 3 */
>        HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
>        HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
>        HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
>        HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
>        HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
>        HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
>        HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
>        HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
>        HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
>        HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
>        HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
>        HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
>        HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
>        HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
>        HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
>        HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
>
>        /* Round 4 */
>        II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
>        II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
>        II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
>        II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
>        II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
>        II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
>        II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
>        II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
>        II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
>        II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
>        II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
>        II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
>        II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
>        II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
>        II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
>        II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
>
>        state[0] += a;
>        state[1] += b;
>        state[2] += c;
>        state[3] += d;
>
>        /* Zeroize sensitive information. */
>        x[] = 0;
>      }
>
>      /* Encodes input (uint) into output (ubyte). Assumes len is
>        a multiple of 4.
>       */
>      private static void Encode (ubyte *output, uint *input, uint len)
>      {
> 	uint i, j;
>
> 	for (i = 0, j = 0; j < len; i++, j += 4)
> 	{
> 	    uint u = input[i];
> 	    output[j]   = cast(ubyte)(u);
> 	    output[j+1] = cast(ubyte)(u >> 8);
> 	    output[j+2] = cast(ubyte)(u >> 16);
> 	    output[j+3] = cast(ubyte)(u >> 24);
> 	}
>      }
>
>      /* Decodes input (ubyte) into output (uint). Assumes len is
>        a multiple of 4.
>       */
>      private static void Decode (uint *output, ubyte *input, uint len)
>      {
> 	uint i, j;
>
> 	for (i = 0, j = 0; j < len; i++, j += 4)
> 	{
> 	    version (LittleEndian)
> 	    {
> 		output[i] = *cast(uint*)&input[j];
> 	    }
> 	    else
> 	    {
> 		output[i] = (cast(uint)input[j]) | ((cast(uint)input[j+1]) << 8) |
> 			((cast(uint)input[j+2]) << 16) | ((cast(uint)input[j+3]) << 24);
> 	    }
> 	}
>      }
> }
>
> /*************************************
>   * Computes MD5 digest of array of data
>   */
>
> void sum(ubyte[16] digest, void[] data)
> {
>      MD5_CTX context;
>
>      context.start();
>      context.update(data);
>      context.finish(digest);
> }
>
> /* Prints a message digest in hexadecimal.
>   */
> void printDigest(ubyte digest[16])
> {
>      foreach (ubyte u; digest)
> 	printf("%02x", u);
> }
>
> unittest
> {
>      debug(md5) printf("std.md5.unittest\n");
>
>      ubyte[16] digest;
>
>      printf("BEFORE: "); for(int i = 0; i < 16; i++) printf("%03d,",digest[i]); printf("\n");
>      sum (digest, "");
>      printf("AFTER:  "); for(int i = 0; i < 16; i++) printf("%03d,",digest[i]); printf("\n");
>      assert(digest == cast(ubyte[])x"d41d8cd98f00b204e9800998ecf8427e");
>
>      sum (digest, "a");
>      assert(digest == cast(ubyte[])x"0cc175b9c0f1b6a831c399e269772661");
>
>      sum (digest, "abc");
>      assert(digest == cast(ubyte[])x"900150983cd24fb0d6963f7d28e17f72");
>
>      sum (digest, "message digest");
>      assert(digest == cast(ubyte[])x"f96b697d7cb7938d525a2f31aaf161d0");
>
>      sum (digest, "abcdefghijklmnopqrstuvwxyz");
>      assert(digest == cast(ubyte[])x"c3fcd3d76192e4007dfb496cca67e13b");
>
>      sum (digest, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
>      assert(digest == cast(ubyte[])x"d174ab98d277d9f5a5611c2c9f419d9f");
>
>      sum (digest,
> 	"1234567890123456789012345678901234567890"
> 	"1234567890123456789012345678901234567890");
>      assert(digest == cast(ubyte[])x"57edf4a22be3c955ac49da2e2107b67a");
>
> }
>
> int main(char[][] args)
> {
> 	for (int i = 1; i < args.length; i++)
> 		MDFile(args[i]);
> 	return 0;
> }
>
> /* Digests a file and prints the result. */
> void MDFile(char[] filename)
> {
> 	FILE* file;
> 	MD5_CTX context;
> 	int len;
> 	ubyte [4 * 1024] buffer;
> 	ubyte digest[16];
>
> 	if ((file = fopen(std.string.toStringz(filename), "rb")) == null)
> 		printf("%.*s can't be opened\n", filename);
> 	else
> 	{
> 		context.start();
> 		while ((len = fread(buffer, 1, buffer.sizeof, file)) != 0)
> 			context.update(buffer[0 .. len]);
> 		context.finish(digest);
> 		fclose(file);
>
> 		printf("MD5 (%.*s) = ", filename);
> 		printDigest(digest);
> 		printf("\n");
> 	}
> }
>
> Regan

April 14, 2005
In dmd-120 none of the std.md5 unittests pass. dmd-119 was ok.

"k2" <k2_member@pathlink.com> wrote in message news:d3l4l4$8cf$1@digitaldaemon.com...
> MD5.finish always return 0.
>
> ---
> win32 DMD 0.120
>
> 


April 15, 2005
I was just going to say that MD5 worked on 119.  So, I guess we figured it out. I suggest for the k2 to go back to 119 and try.  I know it works there.

jic

Ben Hinkle says...
>
>In dmd-120 none of the std.md5 unittests pass. dmd-119 was ok.
>
>"k2" <k2_member@pathlink.com> wrote in message news:d3l4l4$8cf$1@digitaldaemon.com...
>> MD5.finish always return 0.
>>
>> ---
>> win32 DMD 0.120
>>
>> 
>
>


April 15, 2005
Okay,  I'll try 0.119. Thanks all.


April 15, 2005
"k2" <k2_member@pathlink.com> wrote in message news:d3l4l4$8cf$1@digitaldaemon.com...
> MD5.finish always return 0.

You're right. I have it fixed now.