Advertisement
Guest User

Untitled

a guest
May 28th, 2018
465
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 8.35 KB | None | 0 0
  1. #lang racket
  2.  
  3. ;;;; fast modular exponentiation. From the textbook, section 1.2
  4.  
  5. (define (expmod b e m)
  6.   (cond ((zero? e) 1)
  7.         ((even? e)
  8.          (remainder (square (expmod b (/ e 2) m))
  9.                     m))
  10.         (else
  11.          (remainder (* b (expmod b (- e 1) m))
  12.                     m))))
  13.  
  14. (define (square x) (* x x))
  15.  
  16.  
  17. ;;; An RSA key consists of a modulus and an exponent.
  18.  
  19. (define make-key cons)
  20. (define key-modulus car)
  21. (define key-exponent cdr)
  22.  
  23. (define (RSA-transform number key)
  24.   (expmod number (key-exponent key) (key-modulus key)))
  25.  
  26.  
  27. ;;;; generating RSA keys
  28.  
  29. ;;; To choose a prime, we start searching at a random odd number in a
  30. ;;; specifed range
  31.  
  32. (define (choose-prime smallest range)
  33.   (let ((start (+ smallest (choose-random range))))
  34.     (search-for-prime (if (even? start) (+ start 1) start))))
  35.  
  36. (define (search-for-prime guess)
  37.   (if (fast-prime? guess 2)
  38.       guess
  39.       (search-for-prime (+ guess 2))))
  40.  
  41. ;;; The following procedure picks a random number in a given range,
  42. ;;; but makes sure that the specified range is not too big for
  43. ;;; Scheme's RANDOM primitive.
  44.  
  45. (define choose-random
  46.   ;; restriction of Scheme RANDOM primitive
  47.   (let ((max-random-number (expt 10 18)))
  48.     (lambda (n)
  49.       (random (floor (min n max-random-number))))))
  50.  
  51.  
  52. ;;; The Fermat test for primality, from the texbook section 1.2.6
  53.  
  54. (define (fermat-test n)
  55.     (let ((a (choose-random n)))
  56.       (= (expmod a n n) a)))
  57.  
  58. (define (fast-prime? n times)
  59.     (cond ((zero? times) true)
  60.           ((fermat-test n) (fast-prime? n (- times 1)))
  61.           (else false)))
  62.  
  63.  
  64. ;;; RSA key pairs are pairs of keys
  65.  
  66. (define make-key-pair cons)
  67. (define key-pair-public car)
  68. (define key-pair-private cdr)
  69.  
  70. ;;; generate an RSA key pair (k1, k2).  This has the property that
  71. ;;; transforming by k1 and transforming by k2 are inverse operations.
  72. ;;; Thus, we can use one key as the public key andone as the private key.
  73.  
  74. (define (generate-RSA-key-pair)
  75.   (let ((size (expt 2 14)))
  76.     ;; we choose p and q in the range from 2^14 to 2^15.  This insures
  77.     ;; that the pq will be in the range 2^28 to 2^30, which is large
  78.     ;; enough to encode four characters per number.
  79.     (let ((p (choose-prime size size))
  80.           (q (choose-prime size size)))
  81.     (if (= p q)       ;check that we haven't chosen the same prime twice
  82.         (generate-RSA-key-pair)     ;(VERY unlikely)
  83.         (let ((n (* p q))
  84.               (m (* (- p 1) (- q 1))))
  85.           (let ((e (select-exponent m)))
  86.             (let ((d (invert-modulo e m)))
  87.               (make-key-pair (make-key n e) (make-key n d)))))))))
  88.  
  89.  
  90. ;;; The RSA exponent can be any random number relatively prime to m
  91.  
  92. (define (select-exponent m)
  93.   (let ((try (choose-random m)))
  94.     (if (= (gcd try m) 1)
  95.         try
  96.         (select-exponent m))))
  97.  
  98.  
  99. ;;; Invert e modulo m
  100.  
  101. (define (invert-modulo e m)
  102.   (if (= (gcd e m) 1)
  103.       (let ((y (cdr (solve-ax+by=1 m e))))
  104.         (modulo y m))                   ;just in case y was negative
  105.       (error "gcd not 1" e m)))
  106.  
  107.  
  108. ;;; solve ax+by=1
  109. ;;; The idea is to let a=bq+r and solve bx+ry=1
  110.  
  111. (define (solve-ax+by=1 a b)
  112. (define (extended-gcd a b)
  113.   (let loop ([s 0] [t 1] [r b]
  114.              [old-s 1] [old-t 0] [old-r a])
  115.     (if (= r 0)
  116.         (cons old-s old-t)
  117.         (let ((q (quotient old-r r)))
  118.           (loop (- old-s (* q s))
  119.                 (- old-t (* q t))
  120.                 (- old-r (* q r))
  121.                 s t r)))))
  122.   (extended-gcd a b))
  123.  
  124. ;;; Actual RSA encryption and decryption
  125.  
  126. (define (RSA-encrypt string key1)
  127.   (RSA-convert-list (string->intlist string) key1))
  128.  
  129. (define (RSA-convert-list intlist key)
  130.   (let ((n (key-modulus key)))
  131.     (define (convert l sum)
  132.       (if (null? l)
  133.           '()
  134.           (let ((x (RSA-transform (modulo (- (car l) sum) n)
  135.                                   key)))
  136.             (cons x (convert (cdr l) x)))))
  137.     (convert intlist 0)))
  138.  
  139. (define (RSA-decrypt intlist key2)
  140.   (intlist->string (RSA-unconvert-list intlist key2)))
  141.  
  142. (define (RSA-unconvert-list intlist key)
  143.    (let ((n (key-modulus key)))
  144.     (define (convert l sum)
  145.       (if (null? l)
  146.           '()
  147.           (let ((x (modulo (+ (RSA-transform (car l) key) sum) n)))
  148.             (cons x (convert (cdr l) (car l))))))
  149.     (convert intlist 0)))
  150.  
  151.  
  152. ;;;; Digital signatures
  153.  
  154. ;;; The following routine compresses a list of numbers to a single
  155. ;;; number for use in creating digital signatures.
  156.  
  157. (define (compress intlist)
  158.   (define (add-loop l)
  159.     (if (null? l)
  160.         0
  161.         (+ (car l) (add-loop (cdr l)))))
  162.   (modulo (add-loop intlist) (expt 2 28)))
  163.  
  164.  
  165. ;;; XXX: Define the data structure that represents signed messages here
  166. (define (make-signed-message sign message) (cons sign message))
  167. (define (message m) (cdr m))
  168. (define (signature s) (car s))
  169.  
  170.  
  171.  
  172.  
  173. ;;; Encrypting and signing a message
  174.  
  175. (define (encrypt-and-sign message recipient-public-key sender-private-key)
  176.   (let ((enc-msg
  177.          (RSA-encrypt message recipient-public-key)))
  178.     (make-signed-message (RSA-transform (compress enc-msg) sender-private-key) enc-msg)))
  179.  
  180.  
  181. (define (authenticate-and-decrypt cyphertext recipient-private-key sender-public-key)
  182.   (cond [(= (compress (message cyphertext)) (RSA-transform (signature cyphertext) sender-public-key))
  183.          (RSA-decrypt (message cyphertext) recipient-private-key)]
  184.         [else (error "Niepoprawny podpis")]))
  185.  
  186. ;;;; searching for divisors.
  187.  
  188. ;;; The following procedure is very much like the find-divisor
  189. ;;; procedure of section 1.2 of the text, except that it increments
  190. ;;; the test divisor by 2 each time.  You should be careful to call
  191. ;;; it only with odd numbers n.
  192.  
  193. (define (smallest-divisor n)
  194.   (find-divisor n 3))
  195.  
  196. (define (find-divisor n test-divisor)
  197.   (cond ((> (square test-divisor) n) n)
  198.         ((divides? test-divisor n) test-divisor)
  199.         (else (find-divisor n (+ test-divisor 2)))))
  200.  
  201. (define (divides? a b)
  202.   (= (remainder b a) 0))
  203.  
  204.  
  205.  
  206. ;;;; converting between strings and numbers
  207.  
  208. ;;; The following procedures are used to convert between strings, and
  209. ;;; lists of integers in the range 0 through 2^28.  You are not
  210. ;;; responsible for studying this code -- just use it.
  211.  
  212. ;;; Convert a string into a list of integers, where each integer
  213. ;;; encodes a block of characters.  Pad the string with spaces if the
  214. ;;; length of the string is not a multiple of the blocksize.
  215.  
  216. (define (string->intlist string)
  217.   (let ((blocksize 4))
  218.     (let ((padded-string (pad-string string blocksize)))
  219.       (let ((length (string-length padded-string)))
  220.         (block-convert padded-string 0 length blocksize)))))
  221.  
  222. (define (block-convert string start-index end-index blocksize)
  223.   (if (= start-index end-index)
  224.       '()
  225.       (let ((block-end (+ start-index blocksize)))
  226.         (cons (charlist->integer
  227.            (string->list (substring string start-index block-end)))
  228.               (block-convert string block-end end-index blocksize)))))
  229.  
  230. (define (pad-string string blocksize)
  231.   (let ((rem (remainder (string-length string) blocksize)))
  232.     (if (= rem 0)
  233.         string
  234.         (string-append string (make-string (- blocksize rem) #\Space)))))
  235.  
  236. ;;; Encode a list of characters as a single number
  237. ;;; Each character gets converted to an ascii code between 0 and 127.
  238. ;;; Then the resulting number is c[0]+c[1]*128+c[2]*128^2,...
  239.  
  240. (define (charlist->integer charlist)
  241.   (let ((n (char->integer (car charlist))))
  242.     (if (null? (cdr charlist))
  243.         n
  244.         (+ n (* 128 (charlist->integer (cdr charlist)))))))
  245.  
  246. ;;; Convert a list of integers to a string. (Inverse of
  247. ;;; string->intlist, except for the padding.)
  248.  
  249. (define (intlist->string intlist)
  250.   (list->string
  251.    (apply
  252.     append
  253.     (map integer->charlist intlist))))
  254.  
  255.  
  256.  
  257. ;;; Decode an integer into a list of characters.  (This is essentially
  258. ;;; writing the integer in base 128, and converting each "digit" to a
  259. ;;; character.)
  260.  
  261. (define (integer->charlist integer)
  262.   (if (< integer 128)
  263.       (list (integer->char integer))
  264.       (cons (integer->char (remainder integer 128))
  265.             (integer->charlist (quotient integer 128)))))
  266.  
  267. ;;;; Some initial test data
  268.  
  269. (define test-key-pair1
  270.   (make-key-pair
  271.    (make-key 816898139 180798509)
  272.    (make-key 816898139 301956869)))
  273.  
  274. (define test-key-pair2
  275.   (make-key-pair
  276.    (make-key 513756253 416427023)
  277.    (make-key 513756253 462557987)))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement