;; 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: