From: ···········@charter.net
Subject: RC4 encryption in lisp
Date: 
Message-ID: <87em0ricq1.fsf@bobo.spike.home>
Hi all,

I've been trying to teach myself lisp for a while now.  Below is
some lisp code to encrypt a message using the RC4 algorithm.  It
is basically a literal translation of the C code for RC4 encryption
available on the internet.  It produces the same results as the
test vectors given with the C code, so I believe it is correct.

What I'd like to know is, is there a 'better' way to write this.
Something that looks less like C code.  

I'm not trying to squeeze maximum performance out of this, it's just
an exercise.

(defun make-new-rc4-codebook (key)
  "Return an RC4 codebook initialized with key.
   Key is 1 to 256 8 bit integers"
  (let
      ((codebook (make-array '(256) :initial-element 0))
       (index1 0)
       (index2 0)
       (tmp 0)
       (key-length (length key)))
    
       (do ((n 0 (+ 1 n)))
           ((= n 256) nil)
         (setf (aref codebook n) n))

       (do ((n 0 (+ 1 n)))
           ((= n 256) codebook)
         (setf index2 (mod (+ (aref key index1) (aref codebook n) index2) 256))

         (setf tmp (aref codebook n))
         (setf (aref codebook n) (aref codebook index2))
         (setf (aref codebook index2) tmp)

         (setf index1 (mod (+ 1 index1) key-length)))))

(defun rc4-crypt (key msg)
  "Encrypt msg using rc4 algorithm with key given"
  (let ((codebook (make-new-rc4-codebook key))
        (x 0)
        (y 0)
        (tmp nil))
    (do ((n 0 (+ 1 n)))
        ((= n (length msg)) msg)
      
      (setf y (mod (+ (setf tmp (aref codebook (setf x (mod (+ x 1) 
							    256))))
                      y)
                   256))

      (setf (aref codebook x) (aref codebook y))
      (setf (aref codebook y) tmp)

      (setf (aref msg n) (mod (logxor (aref msg n) 
                                      (aref codebook (mod (+ (aref codebook x)
                                                             (aref codebook y))
                                                          256)))
                              256)))))

(defun run-tests ()
  "Run the tests"
;;   Test vector 0
;;   Key: 0x01 0x23 0x45 0x67 0x89 0xab 0xcd 0xef 
;;   Input: 0x01 0x23 0x45 0x67 0x89 0xab 0xcd 0xef 
;;   0 Output: 0x75 0xb7 0x87 0x80 0x99 0xe0 0xc5 0x96 
(let ((key (make-array '(8) 
        :initial-contents '(#x1 #x23 #x45 #x67 #x89 #xab #xcd #xef)))
      (msg (make-array '(8) 
        :initial-contents '(#x1 #x23 #x45 #x67 #x89 #xab #xcd #xef)))
      (*print-base* 16))
  (print "key")
  (print key)
  (print "Input msg")
  (print msg)
  (print "output msg")
  (print (rc4-crypt key msg))
;;   Test vector 1
;;   Key: 0x01 0x23 0x45 0x67 0x89 0xab 0xcd 0xef 
;;   Input: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
;;   0 Output: 0x74 0x94 0xc2 0xe7 0x10 0x4b 0x08 0x79 
  (setf key (make-array '(8) 
        :initial-contents '(#x1 #x23 #x45 #x67 #x89 #xab #xcd #xef)))
  (setf msg (make-array '(8) 
        :initial-contents '(0 0 0 0 0 0 0 0)))
  (print "key")
  (print key)
  (print "Input msg")
  (print msg)
  (print "output msg")
  (print (rc4-crypt key msg))
   
;;   Test vector 2
;;   Key: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
;;   Input: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
;;   0 Output: 0xde 0x18 0x89 0x41 0xa3 0x37 0x5d 0x3a 
   (setf key (make-array '(8) :initial-contents '(0 0 0 0 0 0 0 0)))
   (setf msg (make-array '(8) :initial-contents '(0 0 0 0 0 0 0 0)))
  (print "key")
  (print key)
  (print "Input msg")
  (print msg)
  (print "output msg")
   (print (rc4-crypt key msg))))
From: Rainer Joswig
Subject: Re: RC4 encryption in lisp
Date: 
Message-ID: <joswig-728AE9.00574705112000@news.is-europe.net>
In article <··············@bobo.spike.home>, ···········@charter.net 
wrote:

> Hi all,
> 
> I've been trying to teach myself lisp for a while now.  Below is
> some lisp code to encrypt a message using the RC4 algorithm.  It
> is basically a literal translation of the C code for RC4 encryption
> available on the internet.  It produces the same results as the
> test vectors given with the C code, so I believe it is correct.
> 
> What I'd like to know is, is there a 'better' way to write this.
> Something that looks less like C code.  

Maybe there is. You could use some more built-in functionality
like DOTIMES, LOOP and ROTATEF. Example:

(defun make-new-rc4-codebook (key)
  "Return an RC4 codebook initialized with key.
   Key is 1 to 256 8 bit integers"
  (let ((codebook (make-array '(256) :initial-element 0))
        (key-length (length key)))
    (dotimes (n 256)
      (setf (aref codebook n) n))
    (loop for n below 256
          for index1 = 0 then (mod (1+ index1) key-length)
          with index2 = 0
          do (setf index2 (mod (+ (aref key index1)
                                  (aref codebook n)
                                  index2)
                               256))
          do (rotatef (aref codebook n) (aref codebook index2)))
    codebook))

But this really doesn't change that much.


> (defun run-tests ()
>   "Run the tests"

For experimenting with algorithms it is sometimes
quite handy to use a regression tester.

; deftest NAME FORM &rest VALUES

(rt:deftest "test1"
  (rc4-crypt (make-array '(8) :initial-contents '(#x1 #x23 #x45 #x67 #x89 #xab #xcd #xef))
             (make-array '(8) :initial-contents '(#x1 #x23 #x45 #x67 #x89 #xab #xcd #xef)))
  #(#x75 #xb7 #x87 #x80 #x99 #xe0 #xc5 #x96))

(rt:do-tests)

You would need to modify the "RT" regression tester from
the CMU Lisp archive for your purpose.

-- 
Rainer Joswig, Hamburg, Germany
Email: ·············@corporate-world.lisp.de
Web: http://corporate-world.lisp.de/