Last active
August 29, 2015 14:13
-
-
Save bjhaid/dd91f35e638715019673 to your computer and use it in GitHub Desktop.
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 Crytopals do | |
use Bitwise | |
# http://en.wikipedia.org/wiki/Letter_frequency | |
@freq_english %{ | |
'a' => 8.167,'b' => 1.492,'c' => 2.782,'d' => 4.253,'e' => 12.702,'f' => 2.228,'g' => 2.015,'h' => 6.094,'i' => 6.966, | |
'j' => 0.153,'k' => 0.772,'l' => 4.025,'m' => 2.406,'n' => 6.749,'o' => 7.507,'p' => 1.929,'q' => 0.095,'r' => 5.987, | |
's' => 6.327,'t'=> 9.056,'u' => 2.758,'v' => 0.978,'w' => 2.360,'x' => 0.150,'y' => 1.974,'z' => 0.074, | |
} | |
def single_char_xor(hex) do | |
decode_hex(hex) |> single_char_ascii_xor | |
end | |
def character_freq(word) when is_binary(word), do: word |> to_char_list |> character_freq | |
def character_freq(word) do | |
freqs = word |> | |
Enum.reduce(%{}, fn(char, map) -> | |
Map.update(map, char, 1, &(&1 + 1)) | |
end) | |
freqs_percent = Enum.reduce(0..255, %{}, fn(char, map) -> | |
Map.put(map, char, 100 * Map.get(freqs, char, 0)/length(word)) | |
end) | |
Enum.reduce(@freq_english, 0, fn({[k],v}, acc) -> | |
v + freqs_percent[k] + acc | |
end) | |
end | |
def single_char_ascii_xor(hex) do | |
Enum.reduce(?A..?z, {0, 0, ""}, fn(x, {orig_freq, y, orig_word}) -> | |
word = Enum.map(hex, &(bxor &1, x)) | |
freq = character_freq(word) | |
if freq > orig_freq do | |
{freq, x, word} | |
else | |
{orig_freq, y, orig_word} | |
end | |
end) | |
end | |
def decode_hex(hex) when is_binary(hex), do: hex |> to_char_list |> decode_hex | |
def decode_hex(hex) do | |
hex |> Enum.chunk(2) |> Enum.map(fn(byte) -> to_string(byte) |> String.to_integer(16) end) | |
end | |
defp codepoints_to_string(codepoints, str \\ "") | |
defp codepoints_to_string([h|rest], str), do: codepoints_to_string(rest, str <> <<h>>) | |
defp codepoints_to_string([], str), do: str | |
end | |
Crytopals.decode_hex("49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d") |> IO.inspect | |
Crytopals.single_char_xor("1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736") |> IO.inspect |
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
# Convert hex to base64 | |
"49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d" |> | |
to_char_list |> | |
Stream.chunk(2) |> | |
Enum.map(fn(arr) -> arr |> to_string |> String.to_integer(16) end) |> | |
:base64.encode | |
# => "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t" | |
# Fixed XOR | |
decode_hex = fn(hex) -> hex |> to_char_list |> Enum.chunk(2) |> Enum.map(fn(byte) -> to_string(byte) |> String.to_integer(16) end) end | |
decode_hex.("1c0111001f010100061a024b53535009181c") |> Enum.zip(decode_hex.("686974207468652062756c6c277320657965")) |> Enum.map(fn({x,y}) -> bxor(x,y) end) |> Enum.map(fn(x) -> Integer.to_string(x, 16) end) |> Enum.join | |
# => "746865206B696420646F6E277420706C6179" | |
# Single-byte XOR cipher | |
decode_hex.("1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736") |> Enum.map(fn(x) -> bxor(x, ?X) end) | |
# => 'Cooking MC\'s like a pound of bacon' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment