; hardware random number generator
(define (take n xs)
(let loop ((n n) (xs xs) (ys '()))
(if (or (zero? n) (null? xs))
(reverse ys)
(loop (- n 1) (cdr xs)
(cons (car xs) ys)))))
(define (rand-letter)
(with-input-from-file "/dev/random" (lambda ()
(do ((i 4 (- i 1)) (r 0 (+ (* r 256) (char->integer (read-char)))))
((zero? i) (integer->char (+ (modulo r 26) 65)))))))
(define (keypad n)
(do ((n n (- n 1)) (cs (list) (cons (rand-letter) cs)))
((zero? n) (list->string cs))))
(define (trigraph msg key)
(define (i->a i) (integer->char (+ i 65)))
(define (a->i a) (- (char->integer a) 65))
(define (tri c k) (i->a (modulo (- 25 (a->i k) (a->i c)) 26)))
(let* ((msg (string->list msg))
(key (take (length msg) (string->list key))))
(list->string (map tri msg key))))
(display (rand-letter)) (newline)
(define key "HDFHIJNULLPVJNHTNKNBAXPYR")
(display (trigraph "ATTACKATDAWN" key)) (newline)
(display (trigraph (trigraph "ATTACKATDAWN" key) key)) (newline)