home *** CD-ROM | disk | FTP | other *** search
/ ftp.eterna.com.au / 2014.06.ftp.eterna.com.au.tar / ftp.eterna.com.au / lisp / idea.el next >
Lisp/Scheme  |  1998-04-14  |  5KB  |  167 lines

  1. ;; multiplication mod (2^16)+1, chopped to 16 bits
  2. ;; works by splitting multiplicand into two 8 bit parts
  3. ;; note that an argument of 0 is treated as if it were 2^16
  4. (defun idea-mul (a b)
  5.   (if (or (= a 0)
  6.       (= b 0))
  7.       (logand (- ?\x10001 a b) ?\xffff)
  8.  
  9.     ;; split a into 8 bit pieces
  10.     (let* ((low (logand a ?\xff))
  11.        (high (ash a -8)))
  12.  
  13.       ;; multiply low and high parts by b
  14.       (setq low (* low b))
  15.       (setq high (* high b))
  16.  
  17.       ;; add overlapped bits of high and low, store in low
  18.       (setq low (+ low (ash (logand ?\xff high) 8)))
  19.       
  20.       ;; shift high so high and low do not overlap
  21.       (setq high (+ (ash high -8) (ash low -16)))
  22.       (setq low (logand low ?\xffff))
  23.  
  24.       ;; product is now (+ (ash high 16) low)
  25.       
  26.       ;; optimized mod operation
  27.       (setq low (- low high))
  28.       (if (<= low 0)
  29.       (logand (+ low ?\x10001) ?\xffff)
  30.     (logand low ?\xffff)))))
  31.  
  32. ;; multiplicative inverse, mod (2^16)+1 (which is prime)
  33. ;; uses extended Euclid algorithm
  34. (defun idea-mul-inv (x)
  35.   (if (= x 0)
  36.       0
  37.     ;; calculate am + bn = d, d = greatest common divisor of m,n.
  38.     ;; if m is prime, then b and n are multiplicative inverses
  39.     (let ((m ?\x10001)
  40.       (n x)
  41.       (a 0)
  42.       (b 1)
  43.       (not-done t))
  44.       (while not-done
  45.     (let ((r (mod m n))
  46.           (q (/ m n))
  47.           (temp b))
  48.       (if (= r 0)
  49.           (setq not-done nil)
  50.         (progn
  51.           (setq m n)
  52.           (setq n r)
  53.           (setq b (- a (* q b)))
  54.           (setq a temp)))))
  55.       (if (< b 0)
  56.       (logand (+ b ?\x10001) ?\xffff)
  57.     (logand b ?\xffff)))))
  58.  
  59.  
  60. (defconst *idea-rounds* 8)
  61. (defconst *idea-subkey-number* 52)
  62. ;; = (+ (* 6 *idea-rounds*) 4)
  63.  
  64. ;; generate internal encryption keys from an external key
  65. ;;
  66. ;; takes a 128-bit key (vector of 8 16-bit words) and returns a vector
  67. ;; of 52 (*idea-subkey-number*) 16-bit subkeys
  68. (defun idea-encrypt-subkeys (key)
  69.   (let ((subkeys (make-vector *idea-subkey-number* 0))
  70.     (idx 0))
  71.     (while (< idx 8)
  72.       (aset subkeys idx (aref key idx))
  73.       (setq idx (1+ idx)))
  74.     (while (< idx *idea-subkey-number*)
  75.       (let* ((idx1 (if (= 0 (mod (1+ idx) 8))
  76.                (- idx 15)
  77.              (- idx 7)))
  78.          (idx2 (if (< (mod (+ idx 2) 8) 2)
  79.                (- idx 14)
  80.              (- idx 6))))
  81.     (aset subkeys idx (logand ?\xffff
  82.                   (logior (ash (aref subkeys idx1) 9)
  83.                       (ash (aref subkeys idx2) -7)))))
  84.       (setq idx (1+ idx)))
  85.     subkeys))
  86.  
  87. (defmacro idea-pop (var)
  88.   "damn elisp's lack of CLisms"
  89.   `(prog1
  90.        (car ,var)
  91.      (setq ,var (cdr ,var))))
  92.   
  93.  
  94. ;; generate internal decryption keys from internal encryption keys
  95. ;;
  96. ;; takes a vector of 52 (*idea-subkey-number*) 16-bit words and
  97. ;; returns the same.
  98. (defun idea-decrypt-subkeys (enc-subkeys)
  99.   (let ((dec-subkeys (make-vector *idea-subkey-number* 0))
  100.     (idx (* 6 *idea-rounds*))
  101.     (enc-list (mapcar #'identity enc-subkeys)))
  102.  
  103.     (aset dec-subkeys (+ idx 0) (idea-mul-inv (idea-pop enc-list)))
  104.     (aset dec-subkeys (+ idx 1) (logand ?\xffff (- (idea-pop enc-list))))
  105.     (aset dec-subkeys (+ idx 2) (logand ?\xffff (- (idea-pop enc-list))))
  106.     (aset dec-subkeys (+ idx 3) (idea-mul-inv (idea-pop enc-list)))
  107.  
  108.     (setq idx (* 6 (1- *idea-rounds*))) 
  109.     (while (>= idx 0)
  110.       (aset dec-subkeys (+ idx 4) (idea-pop enc-list))
  111.       (aset dec-subkeys (+ idx 5) (idea-pop enc-list))
  112.       (aset dec-subkeys (+ idx 0) (idea-mul-inv (idea-pop enc-list)))
  113.  
  114.       (if (= 0 idx)
  115.       (progn
  116.         (aset dec-subkeys (+ idx 1) (logand ?\xffff (- (idea-pop enc-list))))
  117.         (aset dec-subkeys (+ idx 2) (logand ?\xffff (- (idea-pop enc-list)))))
  118.     (progn
  119.       (aset dec-subkeys (+ idx 2) (logand ?\xffff (- (idea-pop enc-list))))
  120.       (aset dec-subkeys (+ idx 1) (logand ?\xffff (- (idea-pop enc-list))))))
  121.  
  122.       (aset dec-subkeys (+ idx 3) (idea-mul-inv (idea-pop enc-list)))
  123.  
  124.       (setq idx (- idx 6)))
  125.  
  126.     dec-subkeys))
  127.  
  128. ;; encrypt a 64-bit block of data (4 16-bit words), using the subkeys provided
  129. (defun idea-cipher-block (data subkeys)
  130.   (let ((word1 (aref data 0))
  131.     (word2 (aref data 1))
  132.     (word3 (aref data 2))
  133.     (word4 (aref data 3))
  134.     (key-list (mapcar #'identity subkeys))
  135.     (idx 0)
  136.     t1 t2)
  137.  
  138.     (while (< idx *idea-rounds*)
  139.       (setq word1 (idea-mul word1 (idea-pop key-list)))
  140.       (setq word2 (logand ?\xffff (+ word2 (idea-pop key-list))))
  141.       (setq word3 (logand ?\xffff (+ word3 (idea-pop key-list))))
  142.       (setq word4 (idea-mul word4 (idea-pop key-list)))
  143.  
  144.       (setq t2 (idea-mul (logxor word1 word3) 
  145.              (idea-pop key-list)))
  146.       (setq t1 (idea-mul (logand ?\xffff (+ t2 (logxor word2 word4)))
  147.              (idea-pop key-list)))
  148.       (setq t2 (logand ?\xffff (+ t1 t2)))
  149.  
  150.       (setq word1 (logxor word1 t1))
  151.       (setq word4 (logxor word4 t2))
  152.  
  153.       (setq t2 (logxor t2 word2))
  154.       (setq word2 (logxor word3 t1))
  155.       (setq word3 t2)
  156.  
  157.       (setq idx (1+ idx)))
  158.  
  159.     (setq word1 (idea-mul word1 (idea-pop key-list)))
  160.     (setq word3 (logand ?\xffff (+ word3 (idea-pop key-list))))
  161.     (setq word2 (logand ?\xffff (+ word2 (idea-pop key-list))))
  162.     (setq word4 (idea-mul word4 (idea-pop key-list)))
  163.  
  164.     (vector word1 word3 word2 word4)))
  165.  
  166. (provide 'idea)
  167.