Created
August 26, 2015 15:07
-
-
Save operator-DD3/cff84da8bdfbe877f26f to your computer and use it in GitHub Desktop.
[Lua] CryptoPals Cipher Challenge 1-2
This file contains 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
local index_table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' | |
function to_binary(integer) | |
local remaining = tonumber(integer) | |
local bin_bits = '' | |
for i = 7, 0, -1 do | |
local current_power = math.pow(2, i) | |
if remaining >= current_power then | |
bin_bits = bin_bits .. '1' | |
remaining = remaining - current_power | |
else | |
bin_bits = bin_bits .. '0' | |
end | |
end | |
return bin_bits | |
end | |
function from_binary(bin_bits) | |
return tonumber(bin_bits, 2) | |
end | |
function string.to_base64(to_encode) | |
local bit_pattern = '' | |
local encoded = '' | |
local trailing = '' | |
for i = 1, string.len(to_encode) do | |
bit_pattern = bit_pattern .. to_binary(string.byte(string.sub(to_encode, i, i))) | |
end | |
-- Check the number of bytes. If it's not evenly divisible by three, | |
-- zero-pad the ending & append on the correct number of ``=``s. | |
if math.mod(string.len(bit_pattern), 3) == 2 then | |
trailing = '==' | |
bit_pattern = bit_pattern .. '0000000000000000' | |
elseif math.mod(string.len(bit_pattern), 3) == 1 then | |
trailing = '=' | |
bit_pattern = bit_pattern .. '00000000' | |
end | |
for i = 1, string.len(bit_pattern), 6 do | |
local byte = string.sub(bit_pattern, i, i+5) | |
local offset = tonumber(from_binary(byte)) | |
encoded = encoded .. string.sub(index_table, offset+1, offset+1) | |
end | |
return string.sub(encoded, 1, -1 - string.len(trailing)) .. trailing | |
end | |
function string.from_base64(to_decode) | |
local padded = to_decode:gsub("%s", "") | |
local unpadded = padded:gsub("=", "") | |
local bit_pattern = '' | |
local decoded = '' | |
for i = 1, string.len(unpadded) do | |
local char = string.sub(to_decode, i, i) | |
local offset, _ = string.find(index_table, char) | |
if offset == nil then | |
error("Invalid character '" .. char .. "' found.") | |
end | |
bit_pattern = bit_pattern .. string.sub(to_binary(offset-1), 3) | |
end | |
for i = 1, string.len(bit_pattern), 8 do | |
local byte = string.sub(bit_pattern, i, i+7) | |
decoded = decoded .. string.char(from_binary(byte)) | |
end | |
local padding_length = padded:len()-unpadded:len() | |
if (padding_length == 1 or padding_length == 2) then | |
decoded = decoded:sub(1,-2) | |
end | |
return decoded | |
end | |
function string.from_hex(str) | |
return (str:gsub('..', function (cc) | |
return string.char(tonumber(cc, 16)) | |
end)) | |
end | |
function string.to_hex(str) | |
return (str:gsub('.', function (c) | |
return string.format('%02x', string.byte(c)) | |
end)) | |
end | |
function fixedXOR(a,b) | |
local out = "" | |
for i = 1, #a-1,2 do | |
a1 = string.sub(a,i,i+1) | |
b1 = string.sub(b,i,i+1) | |
a2 = string.byte(a1:from_hex()) | |
b2 = string.byte(b1:from_hex()) | |
out = out .. string.char(bit.bxor(a2,b2)) | |
end | |
return (out:to_hex()) | |
end | |
ciphertext = '1c0111001f010100061a024b53535009181c' | |
key = '686974207468652062756c6c277320657965' | |
plaintext = fixedXOR(ciphertext,key) | |
expected = '746865206b696420646f6e277420706c6179' | |
io.write('\27[1mCryptoPals Cipher Challenge: Set 1-2\27[m\n\n') | |
io.write('\27[32mCiphertext: \27[m\t',ciphertext,'\n') | |
io.write('\27[32mKey: \27[m\t\t',key,'\n') | |
io.write('\27[32mPlaintext: \27[m\t',plaintext,'\n') | |
io.write('\27[32mExpected:\27[m\t',expected,'\n') | |
io.write('\27[32mDecoded:\27[m\t',plaintext:from_hex(),'\n') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment