All pastes #1177893 Raw Edit

phadthai

public text v1 · immutable
#1177893 ·published 2008-08-18 19:34 UTC
rendered paste body
;; Common Lisp RC4 implementation as an exercise
;; Released into the Public Domain.

;; TODO:
;; - Ideally provide a generic function or method for key scheduling.
;;   key-init method as well as key-random-add should use it.
;; - Attempt to specialize methods afterwards for other objects than strings.
;; - Attempt to cleanup code and optimize further.
;; - Write with-key-init or such macro.
;; - Write stream-type functions for it


(declaim (optimize (speed 3) (safety 1))
	 (inline key-random)
	 (inline key-random-add))

(defpackage :mm-rc4
  (:use :cl)
  (:nicknames :rc4)
  (:documentation "")
  (:export
   #:key-init
   #:key-random-add
   #:key-random
   #:key-destroy))


(in-package :rc4)

(defclass rc4-type ()
  ((x
    :type fixnum
    :accessor x
    :initform 0)
   (y
    :type fixnum
    :accessor y
    :initform 0)
   (state
    :type (array fixnum 256)
    :accessor state
    :initform (make-array 256 :element-type 'fixnum))))


(defgeneric key-init (key data discard))

(defmethod key-init ((k rc4-type) (s string) (discard fixnum))
  (let ((tmp) (id1 0) (id2 0) (slen (length s)))
    (declare (tmp fixnum) (id1 fixnum) (id2 fixnum) (slen fixnum))
    (setf (x k) 0)
    (setf (y k) 0)
    (loop
       for i from 0 to 255
       do (setf (elt (state k) i) i))
    (key-random-add k s discard)))


(defgeneric key-random-add (key data discard))

(defmethod key-random-add ((k rc4-type) (s string) (discard fixnum))
  (let ((tmp) (id1 0) (id2 0) (slen (length s)))
    (loop
       for i from 0 to 255
       do (progn (setf tmp (elt (state k) i))
		 (setf id2
		       (ldb (byte 8 0) (+ (char-code (elt s id1)) tmp id2)))
		 (if (= (incf id1) slen) (setf id1 0) ())
		 (setf (elt (state k) i) (elt (state k) id2))
		 (setf (elt (state k) id2) tmp)))
    (loop
       repeat discard
       do (key-random k))))


(defgeneric key-random (key))

(defmethod key-random ((k rc4-type))
  (let ((tmp))
    (declare (tmp fixnum))
    (setf (x k) (ldb (byte 8 0) (1+ (x k))))
    (setf tmp (elt (state k) (x k)))
    (setf (y k) (ldb (byte 8 0) (+ tmp (y k))))
    (setf (elt (state k) (x k)) (elt (state k) (y k)))
    (setf (elt (state k) (y k)) tmp))
  (elt (state k) (ldb (byte 8 0) (+ (x k) (y k)))))


(defgeneric key-encode (k s))

(defmethod key-encode ((k rc4-type) (s string))
  (let ((slen (1- (length s))))
    (declare (slen fixnum))
    (loop
       for i from 0 to slen
       do (setf (elt s i)
		(code-char
		 (logxor (char-code (elt s i))
			 (key-random k))))))
  s)


(defgeneric key-destroy (k))

(defmethod key-destroy ((k rc4-type))
  (setf (x k) 0)
  (setf (y k) 0)
  (loop
     for i from 0 to 255
     do (setf (elt (state k) i) 0)))



(defvar *k*)
(setf *k* (make-instance 'rc4-type))
(key-init *k* "This is a test" 3072)
;;(key-destroy *k*)