;;; -*- Mode:LISP; Package:CRYPT; Base:10; Readtable:CL -*- ;/* @(#)crypt.c 4.1 (Berkeley) 12/21/80 */ ;/* ; * This program implements the ; * Proposed Federal Information Processing ; * Data Encryption Standard. ; * See Federal Register, March 17, 1975 (40FR12134) ; */ (defvar *IP*) (defvar *FP*) (defvar *PC1_C*) (defvar *PC1_D*) (defvar *shifts*) (defvar *PC2_C*) (defvar *PC2_D*) (defvar *C*) (defvar *D*) (defvar *KS*) (defvar *big-E*) (defvar *little-e*) (defvar *S*) (defvar *P*) (defvar *L*) (defvar *R*) (defvar *tempL*) (defvar *F*) (defvar *block*) (defvar *iobuf*) (defvar *preS*) ;/* ; * The combination of the key and the input, before selection. ; */ (defun initialize () ;/* ; * Initial permutation, ; */ (setq *IP* (make-array 64. :leader-list '(nil *IP*))) (fillarray *IP* '(58 50 42 34 26 18 10 2 60 52 44 36 28 20 12 4 62 54 46 38 30 22 14 6 64 56 48 40 32 24 16 8 57 49 41 33 25 17 9 1 59 51 43 35 27 19 11 3 61 53 45 37 29 21 13 5 63 55 47 39 31 23 15 7 )) ;/* ; * Final permutation, FP = IP^(-1) ; */ (setq *FP* (make-array 64. :leader-list '(nil *FP*))) (fillarray *FP* '(40 8 48 16 56 24 64 32 39 7 47 15 55 23 63 31 38 6 46 14 54 22 62 30 37 5 45 13 53 21 61 29 36 4 44 12 52 20 60 28 35 3 43 11 51 19 59 27 34 2 42 10 50 18 58 26 33 1 41 9 49 17 57 25 )) ;/* ; * Permuted-choice 1 from the key bits ; * to yield C and D. ; * Note that bits 8,16... are left out: ; * They are intended for a parity check. ; */ (setq *PC1_C* (make-array 28. :leader-list '(nil *PC1_C*))) (fillarray *PC1_C* '(57 49 41 33 25 17 9 1 58 50 42 34 26 18 10 2 59 51 43 35 27 19 11 3 60 52 44 36 )) (setq *PC1_D* (make-array 28. :leader-list '(nil *PC1_D*))) (fillarray *PC1_D* '(63 55 47 39 31 23 15 7 62 54 46 38 30 22 14 6 61 53 45 37 29 21 13 5 28 20 12 4 )) ;/* ; * Sequence of shifts used for the key schedule. ; */ (setq *shifts* (make-array 16. :leader-list '(nil *shifts*))) (fillarray *shifts* '(1 1 2 2 2 2 2 2 1 2 2 2 2 2 2 1 )) ;/* ; * Permuted-choice 2, to pick out the bits from ; * the CD array that generate the key schedule. ; */ (setq *PC2_C* (make-array 24. :leader-list '(nil *PC2_C*))) (fillarray *PC2_C* '(14 17 11 24 1 5 3 28 15 6 21 10 23 19 12 4 26 8 16 7 27 20 13 2 )) (setq *PC2_D* (make-array 24. :leader-list '(nil *PC2_D*))) (fillarray *PC2_D* '(41 52 31 37 47 55 30 40 51 45 33 48 44 49 39 56 34 53 46 42 50 36 29 32 )) ;/* ; * The C and D arrays used to calculate the key schedule. ; */ (setq *C* (make-array 28. :leader-list '(nil *C*))) (setq *D* (make-array 28. :leader-list '(nil *D*))) ;/* ; * The key schedule. ; * Generated from the key. ; */ (setq *KS* (make-array '(16. 48.) :leader-list '(nil *KS*))) ;/* ; * The E bit-selection table. ; */ (setq *big-E* (make-array 48. :leader-list '(nil *big-E*))) (setq *little-e* (make-array 48. :leader-list '(nil *little-e*))) (fillarray *little-e* '(32 1 2 3 4 5 4 5 6 7 8 9 8 9 10 11 12 13 12 13 14 15 16 17 16 17 18 19 20 21 20 21 22 23 24 25 24 25 26 27 28 29 28 29 30 31 32 1 )) ;/* ; * The 8 selection functions. ; * For some reason, they give a 0-origin ; * index, unlike everything else. ; */ (setq *S* (make-array '(8 64.) :leader-list '(nil *S*))) (fillarray *S* '(14 4 13 1 2 15 11 8 3 10 6 12 5 9 0 7 0 15 7 4 14 2 13 1 10 6 12 11 9 5 3 8 4 1 14 8 13 6 2 11 15 12 9 7 3 10 5 0 15 12 8 2 4 9 1 7 5 11 3 14 10 0 6 13 15 1 8 14 6 11 3 4 9 7 2 13 12 0 5 10 3 13 4 7 15 2 8 14 12 0 1 10 6 9 11 5 0 14 7 11 10 4 13 1 5 8 12 6 9 3 2 15 13 8 10 1 3 15 4 2 11 6 7 12 0 5 14 9 10 0 9 14 6 3 15 5 1 13 12 7 11 4 2 8 13 7 0 9 3 4 6 10 2 8 5 14 12 11 15 1 13 6 4 9 8 15 3 0 11 1 2 12 5 10 14 7 1 10 13 0 6 9 8 7 4 15 14 3 11 5 2 12 7 13 14 3 0 6 9 10 1 2 8 5 11 12 4 15 13 8 11 5 6 15 0 3 4 7 2 12 1 10 14 9 10 6 9 0 12 11 7 13 15 1 3 14 5 2 8 4 3 15 0 6 10 1 13 8 9 4 5 11 12 7 2 14 2 12 4 1 7 10 11 6 8 5 3 15 13 0 14 9 14 11 2 12 4 7 13 1 5 0 15 10 3 9 8 6 4 2 1 11 10 13 7 8 15 9 12 5 6 3 0 14 11 8 12 7 1 14 2 13 6 15 0 9 10 4 5 3 12 1 10 15 9 2 6 8 0 13 3 4 14 7 5 11 10 15 4 2 7 12 9 5 6 1 13 14 0 11 3 8 9 14 15 5 2 8 12 3 7 0 4 10 1 13 11 6 4 3 2 12 9 5 15 10 11 14 1 7 6 0 8 13 4 11 2 14 15 0 8 13 3 12 9 7 5 10 6 1 13 0 11 7 4 9 1 10 14 3 5 12 2 15 8 6 1 4 11 13 12 3 7 14 10 15 6 8 0 5 9 2 6 11 13 8 1 4 10 7 9 5 0 15 14 2 3 12 13 2 8 4 6 15 11 1 10 9 3 14 5 0 12 7 1 15 13 8 10 3 7 4 12 5 6 11 0 14 9 2 7 11 4 1 9 12 14 2 0 6 10 13 15 3 5 8 2 1 14 7 4 10 8 13 15 12 9 0 3 5 6 11 )) ;/* ; * P is a permutation on the selected combination ; * of the current L and key. ; */ (setq *P* (make-array 32. :leader-list '(nil *P*))) (fillarray *P* '(16 7 20 21 29 12 28 17 1 15 23 26 5 18 31 10 2 8 24 14 32 27 3 9 19 13 30 6 22 11 4 25 )) ;/* ; * The current block, divided into 2 halves. ; */ (setq *L* (make-array 32. :leader-list '(nil *L*))) (setq *R* (make-array 32. :leader-list '(nil *R*))) (setq *tempL* (make-array 32. :leader-list '(nil *tempL*))) (setq *F* (make-array 32. :leader-list '(nil *F*))) ;/* ; * The combination of the key and the input, before selection. ; */ (setq *preS* (make-array 48. :leader-list '(nil *preS*))) (setq *block* (make-array 66. :leader-list '(nil *block*))) (setq *iobuf* (make-array 13. :leader-list '(nil *iobuf*) :type :art-string)) ) ;/* ; * Set up the key schedule from the key. ; */ (defun setkey (key) ; /* ; * First, generate C and D by permuting ; * the key. The low order bit of each ; * 8-bit char is not used, so C and D are only 28 ; * bits apiece. ; */ ; for (i=0; i<28; i++) { ; C[i] = key[PC1_C[i]-1]; ; D[i] = key[PC1_D[i]-1]; ; } (dotimes (i 28.) (setf (aref *C* i) (aref key (- (aref *PC1_C* i) 1))) (setf (aref *D* i) (aref key (- (aref *PC1_D* i) 1)))) ; /* ; * To generate Ki, rotate C and D according ; * to schedule and pick up a permutation ; * using PC2. ; */ ; for (i=0; i<16; i++) { (dotimes (i 16.) ; /* ; * rotate. ; */ ; for (k=0; k>3)&01; ; f[t+1] = (k>>2)&01; ; f[t+2] = (k>>1)&01; ; f[t+3] = (k>>0)&01; ; } (dotimes (j 8) (let (temp k) (setq temp (* 6 j)) (setq k (aref *S* j (+ (ash (aref *preS* (+ temp 0)) 5) (ash (aref *preS* (+ temp 1)) 3) (ash (aref *preS* (+ temp 2)) 2) (ash (aref *preS* (+ temp 3)) 1) (ash (aref *preS* (+ temp 4)) 0) (ash (aref *preS* (+ temp 5)) 4)))) (setq temp (* 4 j)) (setf (aref *F* (+ temp 0)) (logand (ash k -3) 1)) (setf (aref *F* (+ temp 1)) (logand (ash k -2) 1)) (setf (aref *F* (+ temp 2)) (logand (ash k -1) 1)) (setf (aref *F* (+ temp 3)) (logand (ash k -0) 1)))) ; /* ; * The new R is L ^ f(R, K). ; * The f here has to be permuted first, though. ; */ ; for (j=0; j<32; j++) ; R[j] = L[j] ^ f[P[j]-1]; (dotimes (j 32.) (setf (aref *R* j) (logxor (aref *L* j) (aref *F* (1- (aref *P* j)))))) ; /* ; * Finally, the new L (the original R) ; * is copied back. ; */ ; for (j=0; j<32; j++) ; L[j] = tempL[j]; (dotimes (j 32.) (setf (aref *L* j) (aref *tempL* j))) ; } ) ; /* ; * The output L and R are reversed. ; */ ; for (j=0; j<32; j++) { ; t = L[j]; ; L[j] = R[j]; ; R[j] = t; ; } (dotimes (j 32.) (swapf (aref *L* j) (aref *R* j))) ; /* ; * The final output ; * gets the inverse permutation of the very original. ; */ ; for (j=0; j<64; j++) ; block[j] = L[FP[j]-1]; (dotimes (j 64.) (let ((index (1- (aref *FP* j)))) (cond ((< index 32.) (setf (aref block j) (aref *L* index))) (t (setf (aref block j) (aref *R* (- index 32.))))))) ;} ) ;char * (defun crypt (pw salt) ;char *pw; ;char *salt; ;{ ; register i, j, c; ; int temp; ; static char block[66], iobuf[16]; ; for(i=0; i<66; i++) ; block[i] = 0; ; for(i=0; (c= *pw) && i<64; pw++){ ; for(j=0; j<7; j++, i++) ; block[i] = (c>>(6-j)) & 01; ; i++; ; } ; (do ((i 0) ; (char-index 0 (1+ char-index)) ; (end (string-length pw))) ; ((not (and (not (= char-index end)) ; (< i 64.)))) ; (do ((j 0 (1+ j))) ; ((= j 7)) ; (setf (aref *block* i) (logand (ash (aref pw char-index) (- 6 j)) 1)) ; (incf i))) (array-initialize *block* 0) (dotimes (char-index (array-length pw)) (dotimes (bit 7) (setf (aref *block* (+ (* char-index 8) bit)) (ldb (byte 1 (- 6 bit)) (aref pw char-index))))) ; setkey(block); (setkey *block*) ; for(i=0; i<66; i++) ; block[i] = 0; (array-initialize *block* 0) ; for(i=0;i<48;i++) ; E[i] = e[i]; (copy-array-contents *little-e* *big-E*) ; for(i=0;i<2;i++){ (dotimes (i 2) ; c = *salt++; ; iobuf[i] = c; ; if(c>'Z') c -= 6; ; if(c>'9') c -= 7; ; c -= '.'; (let ((c (aref salt i))) (setf (aref *iobuf* i) c) (when (char> c #\Z) (decf c 6)) (when (char> c #\9) (decf c 7)) (decf c #\.) ; for(j=0;j<6;j++){ ; if((c>>j) & 01){ ; temp = E[6*i+j]; ; E[6*i+j] = E[6*i+j+24]; ; E[6*i+j+24] = temp; ; } ; } ; } (dotimes (j 6) (when (not (zerop (logand (ash c (- j)) 1))) (swapf (aref *big-E* (+ (* 6 i) j)) (aref *big-E* (+ (* 6 i) j 24.))))) )) ; for(i=0; i<25; i++) ; encrypt(block,0); (dotimes (i 25.) (encrypt *block* nil)) ; for(i=0; i<11; i++){ ; c = 0; ; for(j=0; j<6; j++){ ; c <<= 1; ; c |= block[6*i+j]; ; } ; c += '.'; ; if(c>'9') c += 7; ; if(c>'Z') c += 6; ; iobuf[i+2] = c; ; } (dotimes (i 11.) (let ((c 0)) (dotimes (j 6.) (setq c (logior (ash c 1) (aref *block* (+ (* 6 i) j))))) (incf c #\.) (when (char> c #\9) (incf c 7)) (when (char> c #\Z) (incf c 6)) (setf (aref *iobuf* (+ i 2)) c))) ; iobuf[i+2] = 0; ; if(iobuf[1]==0) ; iobuf[1] = iobuf[0]; ; return(iobuf); (when (zerop (aref *iobuf* 1)) (setf (aref *iobuf* 1) (aref *iobuf* 0))) ;} *iobuf* ) ;---- ;static char *sccsid = "@(#)crypt.c 4.2 (Berkeley) 7/9/81"; ; ;/* ; * A one-rotor machine designed along the lines of Enigma ; * but considerably trivialized. ; */ ;#define ECHO 010 ;#include (defconst ROTORSZ 256) (defconst MASK 0377) (defvar *t1*) (defvar *t2*) (defvar *t3*) (defun initialize-2 () (setq *t1* (make-array ROTORSZ :initial-element 0)) (setq *t2* (make-array ROTORSZ :initial-element 0)) (setq *t3* (make-array ROTORSZ :initial-element 0)) ) (defun 32-bit-* (a b) (logand #o37777777777 (* a b))) (defun setup-2 (pw) (let ((pw-8 (make-array 8 :type :art-8b)) (salt (make-array 2 :type :art-8b))) (copy-array-contents pw pw-8) (copy-array-contents pw salt) (let ((key (crypt pw-8 salt)) (seed 123.)) (dotimes (i 13.) (setq seed (+ (32-bit-* seed (aref key i)) i))) (dotimes (i ROTORSZ) (setf (aref *t1* i) i)) (dotimes (i ROTORSZ) (setq seed (logand #o377777777 (+ (32-bit-* 5 seed) (aref key (mod i 13.))))) (let* ((random (mod seed 65521)) (k (- (- ROTORSZ 1) i)) (ic (mod (logand random MASK) (+ k 1)))) (setq random (ash random -8)) (swapf (aref *t1* k) (aref *t1* ic)) (when (zerop (aref *t3* k)) (setq ic (mod (logand random MASK) k)) (loop until (not (zerop (aref *t3* ic))) do (setq ic (mod (+ ic 1) k))) (setf (aref *t3* k) ic) (setf (aref *t3* ic) k)))))) (dotimes (i ROTORSZ) (setf (aref *t2* (logand (aref *t1* i) MASK)) i))) (defun main-crypt (pw text) (setup-2 pw) (with-output-to-string (output) (let ((n1 0) (n2 0) (nr2 0) nr1) (dotimes (char-index (array-length text)) (setq nr1 n1) (send output :tyo (- (aref *t2* (logand (- (aref *t3* (logand (+ (aref *t1* (logand (+ (aref text char-index) nr1) MASK)) nr2) MASK)) nr2) MASK)) nr1)) (incf n1) (when (= n1 ROTORSZ) (setq n1 0) (incf n2) (when (= n2 ROTORSZ) (setq n2 0)) (setq nr2 0))))))