Skip to content

Instantly share code, notes, and snippets.

@bjhaid
Last active August 29, 2015 14:13
Show Gist options
  • Save bjhaid/dd91f35e638715019673 to your computer and use it in GitHub Desktop.
Save bjhaid/dd91f35e638715019673 to your computer and use it in GitHub Desktop.
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
# 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