I'm interested in cryptography, so I couldn't pass this opportunity up to figure out what this lib did. So I figured I'd decipher the code, and the easiest way to do that is by rewriting it. Turns out, the actual "encoding" is really simple:
Code: Select all
local rekuey = {}
local function encode_char(plainc, keyc, i, j)
plainc, keyc = plainc:byte(i), keyc:byte(j)
return string.char((plainc + keyc)%255)
end
local function decode_char(encc, keyc, i, j)
encc, keyc = encc:byte(i), keyc:byte(j)
return string.char((encc - keyc)%255)
end
local function code(input, key, f)
local output = {}
for i = 1, #input do
local j = (i-1) % #key + 1
output[i] = f(input, key, i, j)
end
return table.concat(output)
end
function rekuey.encode(plain, key)
return code(plain, key, encode_char)
end
function rekuey.decode(enc, key)
return code(enc, key, decode_char)
end
return rekuey
As you can guess, this doesn't really have any nice properties, it means the key can be broken character-by-character, it's probably vulnerable to known-plaintext etc. It basically comes down to a substitution cipher.
As for speed, I measured the performance, both of kuey and "rekuey", it took my code about a second to do 200,000 decryption attempts (original code took about 1.5 seconds).
Code: Select all
package.preload.love = package.loadlib("/usr/lib/liblove.so", "luaopen_love")
require "love"
require "love.timer"
local kuey = require "kuey"
local rekuey = require "rekuey"
local iterations = 200000
local encoded = rekuey.encode("Love is life!", "love2d")
local function time(lib)
local startTime = love.timer.getTime()
local found = false
for i = 1, iterations do
if lib.decode(encoded, tostring(i)) == "Love is life!" then
found = true
end
end
local endTime = love.timer.getTime()
print(("Found solution: %s\nTime taken: %f"):format(found, endTime-startTime))
end
time(kuey)
time(rekuey)
In short, if you're hoping to do something serious with this cipher: don't. If it's just some simple obfuscation that you don't mind getting beaten (which may be as simple as reading the decryption code...), then sure, go ahead and use it.
EDIT: Using luajit's ffi to get faster string->byte->string conversions I can easily get it up to 1,000,000 decodes per second.
EDIT2: I should probably add a disclaimer, because this might sound harsh. This is a fun way to get going with cryptography yourself, and perhaps you could use this as feedback to make something better, like making sure the results depend on the characters before it, or something of the sort. This post mostly served because I was interested in what your cipher is doing, and to warn people to not rely on it for serious encryption purposes. If your goal is to just hide some save data from casual users, go ahead.