01 July 2009
Vigenere cypher in ruby
Some time ago I implemented the Vigenere as a first look at Python. For some time I’ve wanted to do the same thing in Ruby and I finally found time.
The tests:
1 require 'test/unit' 2 require 'vigenere_cipher' 3 4 class VigenereCipherTest < Test::Unit::TestCase 5 6 def test_should_encrypt_a_string 7 plain_text = 'ATTACKATDAWN'; 8 expected_result = 'LXFOPVEFRNHR'; 9 10 machine = VigenereCipher.new; 11 encrypted_string = machine.encrypt('LEMONLEMONLE',plain_text); 12 13 assert_equal expected_result, encrypted_string 14 end 15 16 def test_should_decrypt_a_string 17 expected_result = 'ATTACKATDAWN'; 18 encrypted_message = 'LXFOPVEFRNHR'; 19 20 machine = VigenereCipher.new; 21 encrypted_message = machine.decrypt('LEMONLEMONLE',encrypted_message); 22 23 assert_equal expected_result, encrypted_message 24 end 25 26 def test_should_loop_around_the_key_when_it_is_short_than_the_text 27 plain_text = 'ATTACKATDAWN'; 28 expected_result = 'JXLSLOSLMEOF'; 29 30 machine = VigenereCipher.new; 31 encrypted_string = machine.encrypt('JESS',plain_text); 32 33 assert_equal expected_result, encrypted_string 34 end 35 36 end
And the implementation:
1 class VigenereCipher 2 3 def encrypt(key, plain_text) 4 transform(key, plain_text, 'encrypt') 5 end 6 7 def decrypt(key, encrypted_message) 8 transform(key, encrypted_message, 'decrypt') 9 end 10 11 private 12 def transform(key, text, method) 13 n = -1 14 text.split(//).map{|letter| transform_letter(letter, calc_key_letter(key, n+=1), method=='encrypt' ? :+ : :- )}.join 15 end 16 17 def transform_letter(letter, key_letter, plus_or_minus) 18 charset_offset = "A"[0] 19 letter_position = letter[0] - charset_offset 20 key_letter_position = key_letter[0]-charset_offset 21 22 letter_shifts_by = letter_position.send(plus_or_minus, key_letter_position) 23 (letter_shifts_by.modulo(26)+charset_offset).chr 24 end 25 26 def calc_key_letter(key, n) 27 n = n.modulo(key.length) 28 key.split(//)[n] 29 end 30 31 end
If you’d like to download the code you can get it from my github account
