64 lines
2.4 KiB
Common Lisp
64 lines
2.4 KiB
Common Lisp
|
;; vigenere.lisp - Simple implementation of a Vigenere cipher.
|
||
|
;;
|
||
|
;; This file is free software under the terms of the GPL3 license. You can find
|
||
|
;; a copy of the license at: https://www.gnu.org/licenses/gpl-3.0.en.html
|
||
|
|
||
|
(defpackage vigenere
|
||
|
(:use :cl)
|
||
|
(:export
|
||
|
:+vigenere-alphabet+ :+vigenere-inverse-alphabet+ :vigenere-letter-char
|
||
|
:vigenere-char-letter :vigenere-add :vigenere-encrypt :vigenere-invert-char
|
||
|
:vigenere-decrypt))
|
||
|
|
||
|
(in-package vigenere)
|
||
|
|
||
|
(defparameter +vigenere-alphabet+
|
||
|
" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789."
|
||
|
"Alphabet for use in `vigenere-encrypt'.")
|
||
|
|
||
|
(defparameter +vigenere-inverse-alphabet+
|
||
|
(loop with alph = (make-array 123 :initial-element 0)
|
||
|
for i below (length +vigenere-alphabet+)
|
||
|
for char = (aref +vigenere-alphabet+ i)
|
||
|
do (setf (aref alph (char-code char)) i)
|
||
|
finally (return alph))
|
||
|
"Inverse lookup table for `vigenere-encrypt'.")
|
||
|
|
||
|
(defun vigenere-letter-char (letter)
|
||
|
"Convert LETTER to a Lisp char object."
|
||
|
(aref +vigenere-alphabet+ letter))
|
||
|
|
||
|
(defun vigenere-char-letter (char)
|
||
|
"Convert a Lisp char object CHAR to a letter."
|
||
|
(aref +vigenere-inverse-alphabet+ (char-code char)))
|
||
|
|
||
|
(defun vigenere-add (elem by)
|
||
|
"Add ELEM and BY under the modulo (length `+vigenere-alphabet+')"
|
||
|
(mod (+ elem by) (length +vigenere-alphabet+)))
|
||
|
|
||
|
(defun vigenere-encrypt (plain key)
|
||
|
"Encrypt PLAIN using a vigenere cipher. This works by shifting each element of
|
||
|
PLAIN by each consecutive elements of KEY, wrapping around if there are no more
|
||
|
elements left in KEY."
|
||
|
(let ((done (make-array (length plain))))
|
||
|
(dotimes (i (length plain) (map 'string 'vigenere-letter-char
|
||
|
done))
|
||
|
(setf (aref done i)
|
||
|
(vigenere-add (vigenere-char-letter (aref plain i))
|
||
|
(vigenere-char-letter
|
||
|
(aref key (mod i (length key)))))))))
|
||
|
|
||
|
(defun vigenere-invert-char (char)
|
||
|
"Invert CHAR. That is, return the character that will invert the effect that
|
||
|
CHAR had during encryption."
|
||
|
(let ((letter (vigenere-char-letter char)))
|
||
|
(vigenere-letter-char (- (length +vigenere-alphabet+) letter))))
|
||
|
|
||
|
(defun vigenere-decrypt (cipher key)
|
||
|
"Decrypt CIPHER using a vigenere cipher, with the key KEY."
|
||
|
(vigenere-encrypt cipher (map 'string 'vigenere-invert-char key)))
|
||
|
|
||
|
;; Local Variables:
|
||
|
;; jinx-local-words: "vigenere"
|
||
|
;; End:
|