[plt-scheme] FFI and MD5

From: Jens Axel Søgaard (jensaxel at soegaard.net)
Date: Wed Jan 31 16:21:11 EST 2007

Hi all,

I am attempting to use the FFI to get to the MD5 component of libcrypto.
As far as I can tell, I am getting the wrong results - or perhaps rather
unexpected results.

The test suite for (lib "md5.ss") is as follows:

(test #"d41d8cd98f00b204e9800998ecf8427e" md5 #"")
(test #"0cc175b9c0f1b6a831c399e269772661" md5 #"a")
(test #"900150983cd24fb0d6963f7d28e17f72" md5 #"abc")
(test #"f96b697d7cb7938d525a2f31aaf161d0" md5 #"message digest")
(test #"c3fcd3d76192e4007dfb496cca67e13b" md5
       #"abcdefghijklmnopqrstuvwxyz")
(test #"d174ab98d277d9f5a5611c2c9f419d9f" md5
       #"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
(test #"57edf4a22be3c955ac49da2e2107b67a" md5
#"12345678901234567890123456789012345678901234567890123456789012345678901234567890")


So the message digest (the md) of #"" is 
#"d41d8cd98f00b204e9800998ecf8427e".


The signature of MD5 is describere in
    <http://www.openssl.org/docs/crypto/md5.html#>
as

    unsigned char *MD5(const unsigned char *d, unsigned long n,
                       unsigned char *md);

Note, that if md=NULL, then the message digest is stored
in a static array, so no allocation is neccessary (since
I'll copy the result afterwards).

However, I get:

 > (md5 #"")
"Ô\u001D\u008CÙ\u008F\u0000\u00B2\u0004é\u0080\t\u0098ìøB~"

 > (md5-attempt2 #"")
"Ô\u001D\u008CÙ\u008F\u0000\u00B2\u0004é\u0080\t\u0098ìøB~"


I suspect I have made an obvious mistake, but I can't
spot it. Any ideas?


(module md5-fast mzscheme
   (require (lib "foreign.ss")
            (all-except (lib "contract.ss")
                        ->)
            (rename (lib "contract.ss")
                    c-> ->))
   (unsafe!)

   (define openssl-crypto
     (case (system-type)
       [(windows)
        (ffi-lib "libeay32")]
       [else
        (ffi-lib "libcrypto")]))


   ; <http://www.openssl.org/docs/crypto/md5.html#>
   ; unsigned char *MD5(const unsigned char *d, unsigned long n, 
unsigned char *md);

   (define MD5
     (get-ffi-obj 'MD5 openssl-crypto
                  (_fun [d : _bytes]
                        [n : _ulong = (bytes-length d)]
                        [md : _pointer] ; 128 bits
                        ->
                        _pointer)))

   (define (md5 d)
     (let ([md (MD5 d #f)])
       (let loop ([i 0] [cs '()])
         (if (= i 16)
             (list->string (map integer->char (reverse cs)))
             (loop (+ i 1) (cons (ptr-ref md _byte i) cs))))))

   (define (md5-attempt2 d)
     (let ([md (malloc _byte 16)])
       (MD5 d md)
       (let loop ([i 0] [cs '()])
         (if (= i 16)
             (list->string (map integer->char (reverse cs)))
             (loop (+ i 1) (cons (ptr-ref md _byte i) cs))))))

   )




Posted on the users mailing list.