#lang racket (require math/number-theory) (define-logger rsa) (current-logger rsa-logger) ;; -| STRING TO NUMBER MAPPING |---------------------------------------------------------------------- (define (bytes->number B) ; We'll need our data in numerical form .. (for/fold ((rv 0)) ((b B)) (+ b (* rv 256)))) (define (number->bytes N) ; .. and back again (define (inr n b) (if (zero? n) b (inr (quotient n 256) (bytes-append (bytes (modulo n 256)) b)))) (inr N (bytes))) ;; -| RSA PUBLIC / PRIVATE FUNCTIONS |---------------------------------------------------------------- ;; The basic definitions... pretty well lifted from the text book! (define ((C e n) p) ;; Just do the arithmetic to demonstrate RSA... ;; breaking large messages into blocks is something for another day. (unless (< p n) (raise-argument-error 'C (format "(and/c integer? (symbol (format "~a-~a" function-base-name s)))) (define-values (n e d) (RSA-keyset function-base-name)) (define my-C (rnm-fn (C e n) "C")) (define my-P (rnm-fn (P d n) "P")) (define my-encrypt (rnm-fn (compose number->bytes my-C bytes->number) "encrypt")) (define my-decrypt (rnm-fn (compose number->bytes my-P bytes->number) "decrypt")) (values my-C my-P my-encrypt my-decrypt (list n e d) (list n e))) ;; -| HEREON IS JUST A LOAD OF CHATTY DEMOS |--------------------------------------------------------- (define (narrated-encrypt-bytes C who plain-text) (define plain-n (bytes->number plain-text)) (define cypher-n (C plain-n)) (define cypher-text (number->bytes cypher-n)) (printf #<number cypher-text)) (define plain-n (P cypher-n)) (define plain-text (number->bytes plain-n)) (printf #< ~s Only she could have done this (only she has the her private key data) -- so this is a signature on the message. Anyone can verify the signature by "decrypting" the message with the public "encryption" key. (A-pub (A-prv msg)) -> ~s But anyone is able to do this, so there is no privacy here. Everyone knows that it can only be Alice at Lymm at noon, but this message is for Bob's eyes only. We need to encrypt this with his public key: (B-pub (A-prv msg)) -> ~s Which is what gets posted to alt.chat.secret-rendezvous Bob decrypts this to get the signed message from Alice: (B-prv (B-pub (A-prv msg))) -> ~s And verifies Alice's signature: (A-pub (B-prv (B-pub (A-prv msg)))) -> ~s Alice genuinely sent the message. And nobody else (on a.c.s-r, at least) has read it. KEYS: Alice's full set: ~s Bob's full set: ~s EOS plain-A-to-B signed-A-to-B unsigned-A-to-B crypt-signed-A-to-B decrypt-signed-A-to-B decrypt-verified-B A-pvt-keys B-pvt-keys))