; Ron's Cipher #4
(define (logxor a b)
(cond ((zero? a) b)
((zero? b) a)
(else
(+ (* (logxor (floor (/ a 2)) (floor (/ b 2))) 2)
(if (even? a)
(if (even? b) 0 1)
(if (even? b) 1 0))))))
(define (rc4-init key)
(let ((kvec (make-vector 256)) (klen (string-length key)) (j 0))
(do ((i 0 (+ i 1))) ((= i 256)) (vector-set! kvec i i))
(do ((i 0 (+ i 1))) ((= i 256) kvec)
(set! j (modulo (+ j (vector-ref kvec i)
(char->integer (string-ref key (modulo i klen)))) 256))
(let ((t (vector-ref kvec i)))
(vector-set! kvec i (vector-ref kvec j))
(vector-set! kvec j t)))))
(define (rc4-stream key)
(let ((i 0) (j 0) (kvec (rc4-init key)))
(lambda ()
(set! i (modulo (+ i 1) 256))
(set! j (modulo (+ j (vector-ref kvec i)) 256))
(let ((t (vector-ref kvec j)))
(vector-set! kvec j (vector-ref kvec i))
(vector-set! kvec i t))
(vector-ref kvec (modulo (+ (vector-ref kvec i) (vector-ref kvec j)) 256)))))
(define (rc4-cipher key text)
(let ((rc4 (rc4-stream key)))
(let loop ((ts (map char->integer (string->list text))) (zs '()))
(if (null? ts) (list->string (map integer->char (reverse zs)))
(loop (cdr ts) (cons (logxor (rc4) (car ts)) zs))))))
(display
(rc4-cipher "SAVVY"
(rc4-cipher "SAVVY"
"PROGRAMMING PRAXIS")))
(newline)
(display
(map char->integer
(string->list
(rc4-cipher "SAVVY"
"PROGRAMMING PRAXIS"))))