Last active
November 10, 2017 16:35
-
-
Save acabreragnz/87482d5b2ea19086761c8faa1fdd6b17 to your computer and use it in GitHub Desktop.
Caesar Cipher, using a different key for each different word (key_seed for word in first place, key_seed + 1 for word in second_place, ...). Also we have a force brute function to find the possible keys
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule CryptoSystem do | |
def encrypt(text, key_seed) do | |
words = String.split(text, " "); | |
words | |
|> Enum.with_index() | |
|> Enum.map(&encrypt_word(&1, key_seed)) | |
|> Enum.join(" ") | |
end | |
defp encrypt_word({word, index}, key_seed) do | |
current_key = calculate_current_key(index, key_seed) | |
offset_word(word, current_key) | |
end | |
defp offset_word(word, offset) do | |
(for c <- to_charlist(word), do: c >= 65 && c <= 90 && rem(c - 65 + offset, 26) + 65 || c) | |
|> List.to_string() | |
end | |
defp calculate_current_key(word_position, key_seed) do | |
current_key = key_seed + word_position | |
cond do | |
current_key > 25 -> rem(key_seed + word_position, 26) + 1 | |
current_key -> current_key | |
end | |
end | |
def decrypt(text, key_seed) do | |
words = String.split(text, " "); | |
words | |
|> Enum.with_index() | |
|> Enum.map(&decrypt_word(&1, key_seed)) | |
|> Enum.join(" ") | |
end | |
defp decrypt_word({word, index}, key_seed) do | |
current_key = calculate_current_key(index, key_seed) | |
unoffset_word(word, current_key) | |
end | |
defp unoffset_word(word, offset) do | |
(for c <- to_charlist(word), do: c >= 65 && c <= 90 && unoffset_char(c, offset) || c) | |
|> List.to_string() | |
end | |
defp unoffset_char(c, offset) do | |
calc = rem(c - 65 - offset, 26) | |
cond do | |
calc < 0 -> calc + 26 + 65 | |
true -> calc + 65 | |
end | |
end | |
def possible_keys(plain_word, encrypted_text) do | |
encrypted_words = String.split(encrypted_text, " ") | |
Enum.flat_map(1..25, &in_text_for_key(&1, plain_word, encrypted_words)) | |
|> Enum.reject(&is_nil/1) | |
|> Enum.uniq() | |
|> Enum.sort() | |
end | |
defp in_text_for_key(key, plain_word, encrypted_words) do | |
encrypted_word = encrypt(plain_word, key) | |
index_in_encrypted_text = find_indexes(encrypted_words, encrypted_word) | |
Enum.map(index_in_encrypted_text, &build_possible_key_if_value(&1, key)) | |
end | |
defp build_possible_key_if_value(index_in_encrypted_text, key) do | |
if index_in_encrypted_text != nil, do: build_possible_key(index_in_encrypted_text, key), else: nil | |
end | |
defp build_possible_key(position_in_text, tried_key) do | |
calc = tried_key - position_in_text | |
if calc <= 0, do: calc + 25, else: calc | |
end | |
defp find_indexes(encrypted_word_from_text, word) do | |
Enum.with_index(encrypted_word_from_text) |> Enum.filter_map(fn {x, _} -> x == word end, fn {_, i} -> i end) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment