class ShiftCiphers::Vigenere

Attributes

alphabet[RW]
key[RW]
nonalphabet_char_strategy[RW]

Public Class Methods

new(key, alphabet: Alphabets::DEFAULT, nonalphabet_char_strategy: :error) click to toggle source
# File lib/shift_ciphers/vigenere.rb, line 5
def initialize(key, alphabet: Alphabets::DEFAULT, nonalphabet_char_strategy: :error)
  validate_key(key, alphabet)
  @key = key
  @alphabet = alphabet
  @nonalphabet_char_strategy = nonalphabet_char_strategy
  set_key_offsets
end

Protected Class Methods

decrypt(ciphertext, key, **options) click to toggle source
# File lib/shift_ciphers/vigenere.rb, line 71
def decrypt(ciphertext, key, **options)
  self.new(key, **options).decrypt(ciphertext)
end
encrypt(plaintext, key, **options) click to toggle source
# File lib/shift_ciphers/vigenere.rb, line 67
def encrypt(plaintext, key, **options)
  self.new(key, **options).encrypt(plaintext)
end

Public Instance Methods

alphabet=(alphabet) click to toggle source
# File lib/shift_ciphers/vigenere.rb, line 19
def alphabet=(alphabet)
  validate_key(key, alphabet)
  @alphabet = alphabet
end
decrypt(ciphertext) click to toggle source
# File lib/shift_ciphers/vigenere.rb, line 28
def decrypt(ciphertext)
  process(ciphertext, false)
end
encrypt(plaintext) click to toggle source
# File lib/shift_ciphers/vigenere.rb, line 24
def encrypt(plaintext)
  process(plaintext, true)
end
key=(key) click to toggle source
# File lib/shift_ciphers/vigenere.rb, line 13
def key=(key)
  validate_key(key, alphabet)
  @key = key
  set_key_offsets
end

Protected Instance Methods

create_offsets_stream() click to toggle source
# File lib/shift_ciphers/vigenere.rb, line 55
def create_offsets_stream
  @key_offsets.cycle
end
process(text, encrypting = true) click to toggle source
# File lib/shift_ciphers/vigenere.rb, line 34
def process(text, encrypting = true)
  offsets_stream = create_offsets_stream
  text.each_char.reduce("") do |result, char|
    char_idx = alphabet.index(char)
    if !char_idx.nil?
      rel_offset = offsets_stream.next * (encrypting ? 1 : -1)
      result << alphabet[(char_idx + rel_offset) % alphabet.size]
    else
      if nonalphabet_char_strategy == :dont_encrypt
        result << char
      else
        raise CipherError.new("Invalid input #{text.inspect}. Character #{char.inspect} is not in the alphabet: #{alphabet.inspect}")
      end
    end
  end
end
set_key_offsets() click to toggle source
# File lib/shift_ciphers/vigenere.rb, line 51
def set_key_offsets
  @key_offsets = @key.chars.map {|c| alphabet.index(c) }
end
validate_key(key, alphabet) click to toggle source
# File lib/shift_ciphers/vigenere.rb, line 59
def validate_key(key, alphabet)
  key.each_char do |char|
    raise CipherError.new("Invalid key #{key.inspect}. Character #{char.inspect} is not in the alphabet: #{alphabet.inspect}") unless alphabet.include?(char)
  end
end