[2/2]
; in `(file ,path)
; in `(string ,s)
; out `(file ,path)
; out '(string unpad?)
; ret file: outspec
; ret string: `(string ,s ,length)
(define (medium-mcrypt algo mode padunit ivlen padadd paddel)
(lambda (inspec outspec key encrypt?)
(let* ((inwhat (car inspec))
(outwhat (car outspec))
(indata (cadr inspec))
(insize (case inwhat
((file) (file-length indata))
((string) (string-length indata))
(else 'error-inwhat)))
(mep (lambda (outport)
(mcrypt-encrypt-port
algo
mode
(if encrypt?
(port-padder
(current-input-port)
(padadd insize padunit))
(current-input-port))
outport
key
(make-string ivlen #\NUL)
encrypt?)))
(doout (case outwhat
((file) (lambda () (call-with-output-file (cadr outspec) mep)))
((string) (lambda () (call-with-output-string mep)))
(else 'error-outwhat)))
(doin (case inwhat
((file) (lambda () (with-input-from-file indata doout)))
((string) (lambda () (with-input-from-string indata doout)))
(else 'error-inwhat)))
(ret (doin)))
(if encrypt?
(case outwhat
((file) outspec)
((string) `(string ,ret ,(string-length ret))))
(case outwhat
((file) (truncate-padding (cadr outspec) paddel padunit)
outspec)
((string) (let* ((rlen (string-length ret))
(del (paddel ret padunit))
(used (- rlen del)))
(if (cadr outspec)
`(string ,(string-head ret used) ,used)
`(string ,ret ,used)))))))))
Here is an AES cbc example with strings:
$ 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 (medium-mcrypt "rijndael-128" "cbc" 16 16 padadd-pkcs7 paddel-pkcs7))
;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 ]=> (define enc (aes `(string ,text) '(string #f) key #t))
;Value: enc
1 ]=> (car enc)
;Value: string
1 ]=> (caddr enc)
;Value: 48
1 ]=> (md5-sum->hexadecimal (cadr enc))
;Value 13: "7944266105c58cacba328bb8aa98859ba4eabf4880d4f715890b1b9d8a0237a0434d5e497aaee9d0d9ea114437367dc5"
1 ]=> (define dec (aes `(string ,(cadr enc)) '(string #t) key #f))
;Value: dec
1 ]=> dec
;Value 14: (string "How can I run my own instance of this" 37)
1 ]=> (string=? text (cadr dec))
;Value: #t
1 ]=>
And here is an example from file to string to file:
1 ]=> (define enc (aes '(file "bbs.scm") '(string #f) key #t))
;Value: enc
1 ]=> (car enc)
;Value: string
1 ]=> (caddr enc)
;Value: 16592
1 ]=> (define dec (aes `(string ,(cadr enc)) '(file "bbs.scm.dec") key #f))
;Value: dec
1 ]=> dec
;Value 15: (file "bbs.scm.dec")
1 ]=> (string=? (md5-file "bbs.scm") (md5-file "bbs.scm.dec"))
;Value: #t
1 ]=>
$ cmp bbs.scm.dec bbs.scm
$
This removes the need to manually fiddle with paddings and ports.