add openssl/md5
Like `openssl/sha1`, the `openssl/md5` library falls back to the plain Racket `file/md5` implementation if OpenSSL is not available.
This commit is contained in:
parent
7e57274a64
commit
9e716b0422
|
@ -8,6 +8,9 @@
|
||||||
|
|
||||||
@defmodule[file/md5]
|
@defmodule[file/md5]
|
||||||
|
|
||||||
|
See @racketmodname[openssl/md5] for a faster implementation with a
|
||||||
|
slightly different interface.
|
||||||
|
|
||||||
@defproc[(md5 [in (or/c input-port? bytes? string?)]
|
@defproc[(md5 [in (or/c input-port? bytes? string?)]
|
||||||
[hex-encode? boolean? #t]) bytes?]{
|
[hex-encode? boolean? #t]) bytes?]{
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
@(require scribble/manual
|
@(require scribble/manual
|
||||||
(for-label openssl
|
(for-label openssl
|
||||||
racket
|
racket
|
||||||
openssl/sha1))
|
openssl/sha1
|
||||||
|
openssl/md5))
|
||||||
|
|
||||||
@title{OpenSSL: Secure Communication}
|
@title{OpenSSL: Secure Communication}
|
||||||
|
|
||||||
|
@ -649,3 +650,34 @@ until an end-of-file.}
|
||||||
Converts the given byte string to a string representation, where each
|
Converts the given byte string to a string representation, where each
|
||||||
byte in @racket[bstr] is converted to its two-digit hexadecimal
|
byte in @racket[bstr] is converted to its two-digit hexadecimal
|
||||||
representation in the resulting string.}
|
representation in the resulting string.}
|
||||||
|
|
||||||
|
@defproc[(hex-string->bytes [str string?]) bytes?]{
|
||||||
|
|
||||||
|
The inverse of @racket[bytes->hex-string].}
|
||||||
|
|
||||||
|
@; ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
@section{MD5 Hashing}
|
||||||
|
|
||||||
|
@defmodule[openssl/md5]{The @racketmodname[openssl/md5] library
|
||||||
|
provides a Racket wrapper for the OpenSSL library's MD5 hashing
|
||||||
|
functions. If the OpenSSL library cannot be opened, this library logs
|
||||||
|
a warning and falls back to the implementation in
|
||||||
|
@racketmodname[file/md5].}
|
||||||
|
|
||||||
|
@history[#:added "6.0.0.3"]
|
||||||
|
|
||||||
|
@defproc[(md5 [in input-port?]) string?]{
|
||||||
|
|
||||||
|
Returns a 32-character string that represents the MD5 hash (in
|
||||||
|
hexadecimal notation) of the content from @racket[in], consuming all
|
||||||
|
of the input from @racket[in] until an end-of-file.
|
||||||
|
|
||||||
|
The @racket[md5] function composes @racket[bytes->hex-string] with
|
||||||
|
@racket[md5-bytes].}
|
||||||
|
|
||||||
|
@defproc[(md5-bytes [in input-port?]) bytes?]{
|
||||||
|
|
||||||
|
Returns a 16-byte byte string that represents the MD5 hash of the
|
||||||
|
content from @racket[in], consuming all of the input from @racket[in]
|
||||||
|
until an end-of-file.}
|
||||||
|
|
57
racket/collects/openssl/md5.rkt
Normal file
57
racket/collects/openssl/md5.rkt
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#lang racket/base
|
||||||
|
(require ffi/unsafe
|
||||||
|
racket/runtime-path
|
||||||
|
(for-syntax racket/base)
|
||||||
|
(prefix-in r: file/md5)
|
||||||
|
"libcrypto.rkt")
|
||||||
|
|
||||||
|
(provide md5
|
||||||
|
md5-bytes)
|
||||||
|
|
||||||
|
(define _SHA_CTX-pointer _pointer)
|
||||||
|
|
||||||
|
(define MD5_Init
|
||||||
|
(and libcrypto
|
||||||
|
(get-ffi-obj 'MD5_Init libcrypto (_fun _SHA_CTX-pointer -> _int) (lambda () #f))))
|
||||||
|
(define MD5_Update
|
||||||
|
(and libcrypto
|
||||||
|
(get-ffi-obj 'MD5_Update libcrypto (_fun _SHA_CTX-pointer _pointer _long -> _int) (lambda () #f))))
|
||||||
|
(define MD5_Final
|
||||||
|
(and libcrypto
|
||||||
|
(get-ffi-obj 'MD5_Final libcrypto (_fun _pointer _SHA_CTX-pointer -> _int) (lambda () #f))))
|
||||||
|
|
||||||
|
(define (md5-bytes in)
|
||||||
|
(unless (input-port? in) (raise-argument-error 'md5-bytes "input-port?" in))
|
||||||
|
(if MD5_Init
|
||||||
|
(let ([ctx (malloc 256)]
|
||||||
|
[tmp (make-bytes 4096)]
|
||||||
|
[result (make-bytes 16)])
|
||||||
|
(MD5_Init ctx)
|
||||||
|
(let loop ()
|
||||||
|
(let ([n (read-bytes-avail! tmp in)])
|
||||||
|
(unless (eof-object? n)
|
||||||
|
(MD5_Update ctx tmp n)
|
||||||
|
(loop))))
|
||||||
|
(MD5_Final result ctx)
|
||||||
|
result)
|
||||||
|
(r:md5 in #f)))
|
||||||
|
|
||||||
|
(define (md5 in)
|
||||||
|
(unless (input-port? in) (raise-argument-error 'md5 "input-port?" in))
|
||||||
|
(bytes->hex-string (md5-bytes in)))
|
||||||
|
|
||||||
|
;; copied from `file/sha1` --- should be in a separate module,
|
||||||
|
;; instead
|
||||||
|
(define (bytes->hex-string bstr)
|
||||||
|
(let* ([len (bytes-length bstr)]
|
||||||
|
[bstr2 (make-bytes (* len 2))]
|
||||||
|
[digit
|
||||||
|
(lambda (v)
|
||||||
|
(if (v . < . 10)
|
||||||
|
(+ v (char->integer #\0))
|
||||||
|
(+ v (- (char->integer #\a) 10))))])
|
||||||
|
(for ([i (in-range len)])
|
||||||
|
(let ([c (bytes-ref bstr i)])
|
||||||
|
(bytes-set! bstr2 (* 2 i) (digit (arithmetic-shift c -4)))
|
||||||
|
(bytes-set! bstr2 (+ (* 2 i) 1) (digit (bitwise-and c #xF)))))
|
||||||
|
(bytes->string/latin-1 bstr2)))
|
|
@ -23,6 +23,7 @@
|
||||||
(get-ffi-obj 'SHA1_Final libcrypto (_fun _pointer _SHA_CTX-pointer -> _int) (lambda () #f))))
|
(get-ffi-obj 'SHA1_Final libcrypto (_fun _pointer _SHA_CTX-pointer -> _int) (lambda () #f))))
|
||||||
|
|
||||||
(define (sha1-bytes in)
|
(define (sha1-bytes in)
|
||||||
|
(unless (input-port? in) (raise-argument-error 'sha1-bytes "input-port?" in))
|
||||||
(if SHA1_Init
|
(if SHA1_Init
|
||||||
(let ([ctx (malloc 256)]
|
(let ([ctx (malloc 256)]
|
||||||
[tmp (make-bytes 4096)]
|
[tmp (make-bytes 4096)]
|
||||||
|
@ -38,4 +39,5 @@
|
||||||
(r:sha1-bytes in)))
|
(r:sha1-bytes in)))
|
||||||
|
|
||||||
(define (sha1 in)
|
(define (sha1 in)
|
||||||
|
(unless (input-port? in) (raise-argument-error 'sha1 "input-port?" in))
|
||||||
(r:bytes->hex-string (sha1-bytes in)))
|
(r:bytes->hex-string (sha1-bytes in)))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user