(import foreign) (use (srfi 1 4 13)) (define (random-bytes len) (cond-expand (openbsd: (arc4random len)) (linux: (with-input-from-file "/dev/urandom" (lambda () (read-u8vector len)))) (else (with-input-from-file "/dev/random" (lambda () (read-u8vector len)))))) #+openbsd (define (arc4random len) (let ((buf (make-blob len))) ((foreign-lambda void "arc4random_buf" (scheme-pointer void) size_t) buf len) (blob->u8vector buf))) (define wordlist-file "/usr/share/dict/ngerman") (define words (with-input-from-file wordlist-file read-lines)) (define number-of-words (length words)) (define entropy-per-word (inexact->exact (floor (* (/ (log number-of-words) (log 2)) 100)))) (define (main entropy) (let ((needed-words (inexact->exact (ceiling (/ entropy entropy-per-word))))) (print "Loaded word list (" wordlist-file ") with " number-of-words " words.") (print "Generating a phrase of " needed-words " words with an entropy of " entropy-per-word " bits per word.") (let loop ((phrase '()) (n needed-words)) (let* ((r (u8vector->list (random-bytes 2))) (i (+ (arithmetic-shift (car r) 8) (cadr r)))) (if (zero? n) (print "Phrase: '"(string-join (reverse phrase)) "'") (loop (cons (list-ref words (modulo i number-of-words)) phrase) (sub1 n))))))) (main (string->number (cadr (argv))))