[plt-scheme] FFI and MD5
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))))))
)