1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
//! # Vigenere Cipher //! //! Implements the functionality for the Vigenere cipher. //! //! The following is an excerpt from //! [Wikipedia](https://en.wikipedia.org/wiki/Vigenère_cipher). //! > The Vigenère cipher is a method of encrypting alphabetic text by using a series of interwoven //! Caesar ciphers, based on the letters of a keyword. It employs a form of polyalphabetic //! substitution. //! //! > First described by Giovan Battista Bellaso in 1553, the cipher is easy to understand and //! implement, but it resisted all attempts to break it until 1863, three centuries later. This //! earned it the description le chiffre indéchiffrable (French for 'the indecipherable cipher') //! Many people have tried to implement encryption schemes that are essentially Vigenère ciphers. //! In 1863, Friedrich Kasiski was the first to publish a general method of deciphering Vigenère //! ciphers. //! //! > In the 19th century the scheme was misattributed to Blaise de Vigenère (1523 – 1596), and so //! acquired its present name. use crate::{input, Cipher, CipherResult, TABULA_RECTA}; /// A Vigenere cipher implementation. pub struct Vigenere { key: String, } impl Vigenere { /// Takes the key for the Vigenere cipher and returns a corresponding /// Vigenere struct. /// /// # Panics /// * If `key` is not alphabetic. pub fn new(key: &str) -> Self { input::is_alpha(key).expect("`key` must be alphabetic"); Self { key: key.to_ascii_uppercase(), } } } impl Cipher for Vigenere { /// Enciphers the given plaintext (a str reference) using the Vignere cipher /// and returns the ciphertext as a `CipherResult`. /// /// # Example /// ``` /// use ciphers::{Cipher, Vigenere}; /// /// let vigenere = Vigenere::new("FORTIFICATION"); /// /// let ctext = vigenere.encipher("DEFENDTHEEASTWALLOFTHECASTLE"); /// assert_eq!(ctext.unwrap(), "ISWXVIBJEXIGGBOCEWKBJEVIGGQS"); /// ``` fn encipher(&self, ptext: &str) -> CipherResult { input::is_alpha(ptext)?; let ptext = ptext.to_ascii_uppercase(); let key = self.key.as_bytes(); let ctext = ptext .bytes() .enumerate() .map(move |(i, c)| { let y = key[i % key.len()] as usize - 65; let x = c as usize - 65; TABULA_RECTA[y][x] }) .collect(); Ok(String::from_utf8(ctext).unwrap()) } /// Deciphers the given ciphertext (a str reference) using the Vigenere cipher /// and returns the plaintext as a `CipherResult`. /// /// # Example /// ``` /// use ciphers::{Cipher, Vigenere}; /// /// let vigenere = Vigenere::new("FORTIFICATION"); /// /// let ptext = vigenere.decipher("ISWXVIBJEXIGGBOCEWKBJEVIGGQS"); /// assert_eq!(ptext.unwrap(), "DEFENDTHEEASTWALLOFTHECASTLE"); /// ``` fn decipher(&self, ctext: &str) -> CipherResult { input::is_alpha(ctext)?; let ctext = ctext.to_ascii_uppercase(); let key = self.key.as_bytes(); let ptext = ctext .bytes() .enumerate() .map(move |(i, c)| { let y = key[i % key.len()] as usize - 65; TABULA_RECTA[y].iter().position(|&j| j == c).unwrap() as u8 + 65 }) .collect(); Ok(String::from_utf8(ptext).unwrap()) } }