Shift Ciphers gem is simple, yet complete, implementation of classic Caesar and Vigenère ciphers. It also features custom, hardened version of Vigenère cipher, which uses autokey scheme and PRNGs.
Installation
gem install shift_ciphers
Basic usage
require 'shift_ciphers'
plaintext = "Attack at dawn!"
encrypted = ShiftCiphers::Caesar.encrypt(plaintext, offset: 5) # => "Fyyfhp%fy%ifBs^"
decrypted = ShiftCiphers::Caesar.decrypt(encrypted, offset: 5) # => "Attack at dawn!"
decrypted == plaintext # Should be true
encrypted = ShiftCiphers::Vigenere.encrypt(plaintext, "my keyword") # => "W!0uqS3yU=zI3H{"
decrypted = ShiftCiphers::Vigenere.decrypt(encrypted, "my keyword") # => "Attack at dawn!"
decrypted == plaintext # Should be true
encrypted = ShiftCiphers::HardenedVigenere.encrypt(plaintext, "my keyword") # => "$Uj:o 2M9S+<Cq9"
decrypted = ShiftCiphers::HardenedVigenere.decrypt(encrypted, "my keyword") # => "Attack at dawn!"
decrypted == plaintext # Should be true
... or instantiate a cipher, and benefit from stored configuration info (e.g. offset
for Caesar cipher, or key
for Vigenère):
caesar = ShiftCiphers::Caesar.new
caesar.offset = 5
encrypted = caesar.encrypt(plaintext) # => "Fyyfhp%fy%ifBs^"
decrypted = caesar.decrypt(encrypted) # => "Attack at dawn!"
decrypted == plaintext # Should be true
vigenere = ShiftCiphers::Vigenere.new("my keyword")
encrypted = vigenere.encrypt(plaintext) # => "W!0uqS3yU=zI3H{"
decrypted = vigenere.decrypt(encrypted) # => "Attack at dawn!"
decrypted == plaintext # Should be true
strong_vigenere = ShiftCiphers::HardenedVigenere.new("my keyword")
encrypted = strong_vigenere.encrypt(plaintext) # => "$Uj:o 2M9S+<Cq9"
decrypted = strong_vigenere.decrypt(encrypted) # => "Attack at dawn!"
decrypted == plaintext # Should be true
You can customize alphabet used by cipher:
plaintext = "ATTACKATDAWN"
encrypted = ShiftCiphers::Vigenere.encrypt(plaintext, "KEYWORD", alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZ") # => "KXRWQBDDHYSB"
decrypted = ShiftCiphers::Vigenere.decrypt(encrypted, "KEYWORD", alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZ") # => "ATTACKATDAWN"
decrypted == plaintext # Should be true
When you attempt to encrypt a string, which contains character that is not in the cipher's alphabet, then ShiftCiphers::CipherError
is rised:
plaintext = "ATTACK!"
encrypted = ShiftCiphers::Vigenere.encrypt(plaintext, "KEYWORD", alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
# Raises ShiftCiphers::CipherError: Invalid input "ATTACK!". Character "!" is not in the alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
You can avoid this exception by telling cipher not to encrypt characters which are not in its alphabet. This is done by passing nonalphabet_char_strategy
argument to encrypt
/decrypt
class method (or by using nonalphabet_char_strategy=
instance method):
plaintext = "ATTACK AT DAWN!"
encrypted = ShiftCiphers::Vigenere.encrypt(plaintext, "KEYWORD", alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZ", nonalphabet_char_strategy: :dont_encrypt)
decrypted = ShiftCiphers::Vigenere.decrypt(encrypted, "KEYWORD", alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZ", nonalphabet_char_strategy: :dont_encrypt)
puts plaintext # => ATTACK AT DAWN!
puts encrypted # => KXRWQB DD HYSB!
decrypted == plaintext # Should be true