class ShiftCiphers::HardenedVigenere

Attributes

initial_seed[RW]

Public Class Methods

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

Protected Instance Methods

create_offsets_stream() click to toggle source
# File lib/shift_ciphers/hardened_vigenere.rb, line 40
def create_offsets_stream
  RandomOffsetsStream.new(key, alphabet.size - 1, @initial_seed)
end
process(text, encrypting = true) click to toggle source
# File lib/shift_ciphers/hardened_vigenere.rb, line 15
def process(text, encrypting = true)
  stage1 = process_single(text, text.each_char, encrypting)
  process_single(stage1, stage1.each_char.reverse_each, encrypting)
end
process_single(text, text_enumerator, encrypting = true) click to toggle source
# File lib/shift_ciphers/hardened_vigenere.rb, line 20
def process_single(text, text_enumerator, encrypting = true)
  offsets_stream = create_offsets_stream
  plaintext_char = ""
  text_enumerator.reduce("") do |result, char|
    char_idx = alphabet.index(char)
    if !char_idx.nil?
      rel_offset = offsets_stream.next(plaintext_char) * (encrypting ? 1 : -1)
      result_char = alphabet[(char_idx + rel_offset) % alphabet.size]
      plaintext_char = encrypting ? char : result_char
      result << result_char
    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