https://textboard.org/prog/39#t39p126
On the other hand, a lot of functions are undocumented in MIT Scheme, and you have to read the source code if you want to use them. And there isn't exactly a huge community of users outside of the academic world. I wouldn't know where to ask for help.
... and I'm stuck.
https://textboard.org/prog/39#t39p208
There's a stub for an antispam system that was never implemented because I had problems with mit-scheme cryptographic functions.
The contexts are usable as shown in mcrypt-encrypt-port, but they are only needed for efficiency in tight loops or where mcrypt-encrypt-port is unsuitable. Otherwise mcrypt-encrypt-port is more convenient than manual contexts, with one caveat. While the function is forgiving on the IV string's length, it is strict on the input size of block modes, so padding responsibility falls on the caller. Here is a small demo with NUL padding appropriate for text.
$ cat test.scm
(define (simple-mcrypt algo mode padunit ivlen)
(define (pad s)
(let* ((slen (string-length s))
(mod (modulo slen padunit)))
(if (= mod 0)
s
(string-pad-right s (+ slen (- padunit mod)) #\NUL))))
(define trimcs (char-set-invert (char-set #\NUL)))
(lambda (text key encrypt?)
(let ((out (with-input-from-string
(if encrypt?
(pad text)
text)
(lambda ()
(call-with-output-string
(lambda (port)
(mcrypt-encrypt-port
algo
mode
(current-input-port)
port
key
(make-string ivlen #\NUL)
encrypt?)))))))
(if encrypt?
out
(string-trim-right out trimcs)))))
Usage example with basic cbc AES:
$ mit-scheme --load test.scm
[...]
Release 9.1.1 || Microcode 15.3 || Runtime 15.7 || SF 4.41
LIAR/x86-64 4.118 || Edwin 3.116
;Loading "test.scm"... done
1 ]=> (define aes (simple-mcrypt "rijndael-128" "cbc" 16 16))
;Value: aes
1 ]=> (define key (md5-string "secret key"))
;Loading "/usr/lib/x86_64-linux-gnu/mit-scheme/lib/prmhash.so"... done
;Value: key
1 ]=> (define text "How can I run my own instance of this")
;Value: text
1 ]=> (mcrypt-available?)
;Loading "/usr/lib/x86_64-linux-gnu/mit-scheme/lib/prmcrypt.so"... done
;Value: #t
1 ]=> (define cytext (aes text key #t))
;Value: cytext
1 ]=> (md5-sum->hexadecimal cytext)
;Value 13: "7944266105c58cacba328bb8aa98859ba4eabf4880d4f715890b1b9d8a0237a00445293cbcbcc0f205db1aa0f0d63c73"
1 ]=> (define text2 (aes cytext key #f))
;Value: text2
1 ]=> text2
;Value 14: "How can I run my own instance of this"
1 ]=> (string=? text text2)
;Value: #t
1 ]=>
To encrypt arbitrary input a proper padding scheme is needed instead of this small demo with NULs. Files can be processed in the obvious way by substituting call-with-binary-input-file and call-with-binary-output-file.
Here is an upgrade of >>3 with selectable padding scheme and the addition of PKCS#7 padding.
$ cat test.scm
(define (simple-mcrypt algo mode padunit ivlen padin padout)
(lambda (text key encrypt?)
(let ((out (with-input-from-string
(if encrypt?
(padin text padunit)
text)
(lambda ()
(call-with-output-string
(lambda (port)
(mcrypt-encrypt-port
algo
mode
(current-input-port)
port
key
(make-string ivlen #\NUL)
encrypt?)))))))
(if encrypt?
out
(padout out padunit)))))
(define (test-simple-mcrypt engine text key)
(let* ((hidden (engine text key #t))
(revealed (engine hidden key #f)))
(string=? text revealed)))
(define (padin-nul s unit)
(let* ((slen (string-length s))
(mod (modulo slen unit)))
(if (= mod 0)
s
(string-pad-right s (+ slen (- unit mod)) #\NUL))))
(define (padout-nul)
(define trimcs (char-set-invert (char-set #\NUL)))
(lambda (s unit)
(string-trim-right s trimcs)))
(define (padin-pkcs7 s unit)
(let* ((slen (string-length s))
(mod (modulo slen unit))
(used (- unit mod)))
(string-pad-right s (+ slen used) (ascii->char used))))
(define (padout-pkcs7 s unit)
(let* ((slen (string-length s))
(used (char->ascii (string-ref s (- slen 1)))))
(string-head s (- slen used))))
Usage example with cbc AES-256. Strings of NULs are no problem with PKCS#7.
$ mit-scheme --load test.scm
[...]
Release 9.1.1 || Microcode 15.3 || Runtime 15.7 || SF 4.41
LIAR/x86-64 4.118 || Edwin 3.116
;Loading "test.scm"... done
1 ]=> (mcrypt-available?)
;Loading "/usr/lib/x86_64-linux-gnu/mit-scheme/lib/prmcrypt.so"... done
;Value: #t
1 ]=> (define aes (simple-mcrypt "rijndael-256" "cbc" 16 16 padin-nul (padout-nul)))
;Value: aes
1 ]=> (define key (string-append (md5-string "secret key") (md5-string "part two")))
;Loading "/usr/lib/x86_64-linux-gnu/mit-scheme/lib/prmhash.so"... done
;Value: key
1 ]=> (define text "How can I run my own instance of this")
;Value: text
1 ]=> (test-simple-mcrypt aes text key)
;Value: #t
1 ]=> (define aes (simple-mcrypt "rijndael-256" "cbc" 16 16 padin-pkcs7 padout-pkcs7))
;Value: aes
1 ]=> (test-simple-mcrypt aes text key)
;Value: #t
1 ]=> (define text (make-string 55 #\NUL))
;Value: text
1 ]=> text
;Value 13: "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
1 ]=> (test-simple-mcrypt aes text key)
;Value: #t
1 ]=>