Skip to content

Latest commit

 

History

History
83 lines (63 loc) · 3.79 KB

README.md

File metadata and controls

83 lines (63 loc) · 3.79 KB

Shift Ciphers Gem Version Build Status

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