Last active
November 27, 2022 07:22
-
-
Save MCJack123/32c56917dc61da336ec0e8ca6aae39f8 to your computer and use it in GitHub Desktop.
Filesystem encryption program for ComputerCraft
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
if fs.isUnlocked then | |
local args = {...} | |
if args[1] == "lock" or (args[1] == nil and fs.isUnlocked()) then | |
fs.lock() | |
print("The filesystem is now locked.") | |
elseif args[1] == "unlock" or args[1] == nil then | |
fs.unlock() | |
print("The filesystem is now unlocked.") | |
elseif args[1] == "encrypt" then | |
if args[3] == nil then error("Usage: fsencrypt encrypt <infile> <outfile>") end | |
fs.encrypt(args[2], args[3]) | |
print(args[2] .. " has been encrypted as " .. args[3] .. ".") | |
elseif args[1] == "decrypt" then | |
if args[3] == nil then error("Usage: fsencrypt decrypt <infile> <outfile>") end | |
fs.decrypt(args[2], args[3]) | |
print(args[2] .. " has been decrypted as " .. args[3] .. ".") | |
elseif args[1] == "help" then | |
print([[ | |
Usage: | |
fsencrypt | |
Toggles lock status. | |
fsencrypt lock | |
Locks access to encrypted files. | |
fsencrypt unlock | |
Unlocks access to encrypted files. | |
fsencrypt encrypt <infile> <outfile> | |
Encrypts a file. | |
fsencrypt decrypt <infile> <outfile> | |
Decrypts a file. | |
fsencrypt help | |
Displays this help.]]) | |
end | |
return | |
end | |
local aeslua = require "aeslua" | |
local sha2 = require "sha2" | |
local expect = require("cc.expect").expect | |
local sha256 = sha2.sha256 | |
local function sxor(s1, s2) | |
local b1 = {} | |
local b2 = {} | |
local b3 = {} | |
for i=1,#s1 do | |
b1[#b1+1] = string.byte(s1, i) | |
end | |
for i=1,#s2 do | |
b2[#b2+1] = string.byte(s2, i) | |
end | |
for i=1,#b1 do | |
b3[#b3+1] = string.char(bit32.bxor(b1[i], b2[i])) | |
end | |
return table.concat(b3) | |
end | |
local function hex2bin(str) return str:gsub("%x%x", function(s) return string.char(tonumber(s, 16)) end) end | |
local function pbkdf2(hm, pass, salt, it) | |
local u | |
local t | |
u = hex2bin(sha2.hmac(hm, pass, salt.."\1")) | |
t = u | |
for i=2,it do | |
u = hex2bin(sha2.hmac(hm, pass, u)) | |
t = sxor(t, u) | |
end | |
return t | |
end | |
local function iv2bin(iv) | |
local retval = "" | |
for _,v in ipairs(iv) do retval = retval .. string.char(v) end | |
return retval | |
end | |
local key, salt, filetree | |
local orig_fs = fs | |
_G.fs = {getName = orig_fs.getName, getDrive = orig_fs.getDrive, getFreeSpace = orig_fs.getFreeSpace, combine = orig_fs.combine, getDir = orig_fs.getDir, isDriveRoot = orig_fs.isDriveRoot, getCapacity = orig_fs.getCapacity} | |
function fs.unlock(password) | |
math.randomseed(os.epoch("utc")) | |
if not password then | |
write("Please enter the password: ") | |
password = read("\7") | |
end | |
local iv | |
salt = "" | |
if orig_fs.exists("f1a36aae5f891a6c695d12621d1e0ecc4cee1a5e951784d874b8e6ad94de223f") then | |
local file = orig_fs.open("f1a36aae5f891a6c695d12621d1e0ecc4cee1a5e951784d874b8e6ad94de223f", "rb") | |
local t = file.readAll() | |
file.close() | |
salt, iv = t:sub(1, 16), {t:sub(17):byte(1, 16)} | |
else | |
for _ = 1, 16 do salt = salt .. string.char(math.random(0, 255)) end | |
end | |
key = pbkdf2(sha256, password, salt, 2500) | |
password = nil | |
filetree = {} | |
if orig_fs.exists("9f721fc36d10270affc7dbba9594e7665f95e0ad6d1729f5d9c0e6cc18235cf3") then | |
local file = orig_fs.open("9f721fc36d10270affc7dbba9594e7665f95e0ad6d1729f5d9c0e6cc18235cf3", "rb") | |
local str = aeslua.decrypt(key, file.readAll(), 32, aeslua.CBCMODE, iv, true) | |
file.close() | |
if str == nil then | |
key, salt, filetree = nil | |
error("Incorrect password.", 2) | |
end | |
filetree = textutils.unserialize(str) | |
end | |
end | |
local function saveFileTree() | |
if key == nil or filetree == nil then return end | |
local iv = {} | |
if orig_fs.exists("f1a36aae5f891a6c695d12621d1e0ecc4cee1a5e951784d874b8e6ad94de223f") then | |
local file = orig_fs.open("f1a36aae5f891a6c695d12621d1e0ecc4cee1a5e951784d874b8e6ad94de223f", "rb") | |
local t = file.readAll() | |
file.close() | |
iv = {t:sub(17):byte(1, 16)} | |
else | |
for i = 1, 16 do iv[i] = math.random(0, 255) end | |
local file = orig_fs.open("f1a36aae5f891a6c695d12621d1e0ecc4cee1a5e951784d874b8e6ad94de223f", "wb") | |
file.write(salt .. iv2bin(iv)) | |
file.close() | |
end | |
local file = orig_fs.open("9f721fc36d10270affc7dbba9594e7665f95e0ad6d1729f5d9c0e6cc18235cf3", "wb") | |
file.write(aeslua.encrypt(key, textutils.serialize(filetree), 32, aeslua.CBCMODE, iv, true)) | |
file.close() | |
end | |
function fs.isUnlocked() | |
return key ~= nil and salt ~= nil and filetree ~= nil | |
end | |
function fs.lock() | |
saveFileTree() | |
key, salt, filetree = nil | |
end | |
local function splitPath(p) | |
local retval = {} | |
for m in p:gmatch("[^/]+") do table.insert(retval, m) end | |
return retval | |
end | |
local function getFileTree(list, t) | |
if #list == 0 then return t | |
elseif type(t) ~= "table" then return nil | |
else | |
local i = table.remove(list, 1) | |
return getFileTree(list, t[i]) | |
end | |
end | |
local function getFilePath(path) return getFileTree(splitPath(path), filetree) end | |
local function setFileTree(list, v, t) | |
if #list > 1 and t[list[1]] == nil then t[list[1]] = {} end | |
if #list == 0 then error("Critical error while writing encrypted data") | |
elseif #list == 1 then t[list[1]] = v | |
else return setFileTree(list, v, t[table.remove(list, 1)]) end | |
end | |
local function setFilePath(path, v) return setFileTree(splitPath(path), v, filetree) end | |
local shamatch = "^%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x$" | |
local function isSHA(path) return fs.combine(path, ""):match(shamatch) ~= nil or fs.combine(path, "") == ".salt" or fs.combine(path, "") == ".filetree" end | |
function fs.list(dir) | |
expect(1, dir, "string") | |
local ok, retval = pcall(orig_fs.list, dir) | |
local tree = getFilePath(dir) | |
if not ok and type(tree) ~= "table" then error(retval:gsub("^.-:%d: ", ""), 2) end | |
retval = ok and retval or {} | |
if type(tree) == "table" then for k in pairs(tree) do table.insert(retval, k) end end | |
if fs.combine(dir, "") == "" then | |
local keep = {} | |
for _,v in ipairs(retval) do if not isSHA(v) then table.insert(keep, v) end end | |
retval = keep | |
end | |
table.sort(retval) | |
return retval | |
end | |
function fs.exists(path) | |
expect(1, path, "string") | |
if isSHA(path) then return false else return orig_fs.exists(path) or getFilePath(path) ~= nil end | |
end | |
function fs.isDir(path) | |
expect(1, path, "string") | |
if isSHA(path) then return false else return orig_fs.isDir(path) or type(getFilePath(path)) == "table" end | |
end | |
function fs.isReadOnly(path) | |
expect(1, path, "string") | |
return orig_fs.isReadOnly(path) -- more necessary? | |
end | |
function fs.getSize(path) | |
expect(1, path, "string") | |
if isSHA(path) then error("/" .. fs.combine(path, "") .. ": No such file", 2) end | |
local ok, retval = pcall(orig_fs.getSize, path) | |
local tree = getFilePath(path) | |
if not ok and tree == nil then error(retval:gsub("^.-:%d: ", ""), 2) | |
elseif type(tree) == "table" then return 0 | |
elseif ok then return retval end | |
local file = fs.open(path, "rb") | |
retval = #file.readAll() | |
file.close() | |
return retval | |
end | |
function fs.makeDir(path) | |
expect(1, path, "string") | |
if isSHA(path) then error("/" .. fs.combine(path, "") .. ": File exists", 2) | |
elseif filetree == nil then return orig_fs.makeDir(path) | |
elseif type(getFilePath(path)) == "string" then error("/" .. fs.combine(path, "") .. ": File exists", 2) end | |
setFilePath(path, getFilePath(path) or {}) | |
saveFileTree() | |
end | |
function fs.move(from, to) | |
expect(1, from, "string") | |
expect(2, to, "string") | |
if isSHA(from) then error("/" .. fs.combine(from, "") .. ": No such file or directory", 2) | |
elseif isSHA(to) then error("/" .. fs.combine(to, "") .. ": Permission denied", 2) | |
elseif orig_fs.exists(from) or filetree == nil then return orig_fs.move(from, to) | |
elseif getFilePath(from) == nil then error("/" .. fs.combine(from, "") .. ": No such file or directory", 2) | |
elseif getFilePath(to) ~= nil then error("/" .. fs.combine(to, "") .. ": File exists", 2) end | |
setFilePath(to, getFilePath(from)) | |
setFilePath(from, nil) | |
saveFileTree() | |
end | |
function fs.copy(from, to) | |
expect(1, from, "string") | |
expect(2, to, "string") | |
if isSHA(from) then error("/" .. fs.combine(from, "") .. ": No such file or directory", 2) | |
elseif isSHA(to) then error("/" .. fs.combine(to, "") .. ": Permission denied", 2) | |
elseif orig_fs.exists(from) or filetree == nil then return orig_fs.copy(from, to) | |
elseif getFilePath(from) == nil then error("/" .. fs.combine(from, "") .. ": No such file or directory", 2) | |
elseif getFilePath(to) ~= nil then error("/" .. fs.combine(to, "") .. ": File exists", 2) end | |
setFilePath(to, getFilePath(from)) | |
saveFileTree() | |
end | |
function fs.delete(path) | |
expect(1, path, "string") | |
if isSHA(path) then error("/" .. fs.combine(path, "") .. ": Permission denied", 2) | |
elseif orig_fs.exists(path) or filetree == nil then return orig_fs.delete(path) end | |
setFilePath(path, nil) | |
saveFileTree() | |
end | |
function fs.open(path, mode) | |
expect(1, path, "string") | |
expect(2, mode, "string") | |
if isSHA(path) then return nil, ("/" .. fs.combine(path, "") .. (mode:sub(1, 1) ~= "w" and ": No such file" or ": Permission denied")) | |
elseif orig_fs.exists(path) or filetree == nil then return orig_fs.open(path, mode) | |
elseif ({r=1, w=1, a=1, rb=1, wb=1, ab=1})[mode] == nil then return nil, ("/" .. fs.combine(path, "") .. ": Unknown mode") end | |
local contents, pos = "", 1 | |
local isBinary = mode:sub(2, 2) == "b" | |
local closed = false | |
if mode:sub(1, 1) ~= "w" then | |
local iv = getFilePath(path) | |
if type(iv) ~= "string" then return nil, ("/" .. fs.combine(path, "") .. (iv == nil and ": No such file" or ": Is a directory")) end | |
local file, err = orig_fs.open(sha256(fs.combine(path, "") .. iv), "rb") | |
if not file then return file, err end | |
contents = aeslua.decrypt(key, file.readAll(), 32, aeslua.CBCMODE, {iv:byte(1, 16)}, true) | |
file.close() | |
if contents == nil then return nil, "Failed to decrypt file" end | |
if not isBinary then | |
local str = "" | |
for _,v in utf8.codes(contents) do if v < 256 then str = str .. string.char(v) else str = str .. "?" end end | |
contents = str | |
end | |
end | |
if mode:sub(1, 1) == "a" then pos = #contents + 1 end | |
if mode:sub(1, 1) == "r" then return { | |
read = function(n) | |
expect(1, n, "number", "nil") | |
if pos > #contents then return nil | |
elseif closed then error("attempt to use a closed file", 2) | |
elseif n == nil then | |
pos = pos + 1 | |
if isBinary then return contents:byte(pos-1) | |
else return contents:sub(pos-1, pos-1) end | |
else | |
pos = pos + n | |
return contents:sub(pos - n, pos - 1) | |
end | |
end, | |
readLine = function() | |
if pos > #contents then return nil elseif closed then error("attempt to use a closed file", 2) end | |
local retval = "" | |
for c in contents:sub(pos):gmatch(".") do | |
pos = pos + 1 | |
if c == '\n' then break end | |
retval = retval .. c | |
end | |
return retval | |
end, | |
readAll = function() | |
if pos > #contents then return nil elseif closed then error("attempt to use a closed file", 2) end | |
local retval = contents:sub(pos) | |
pos = #contents + 1 | |
return retval | |
end, | |
seek = isBinary and function(whence, offset) | |
expect(1, whence, "string", "nil") | |
expect(2, offset, "number", "nil") | |
if closed then error("attempt to use a closed file", 2) end | |
whence = whence or "cur" | |
offset = offset or 0 | |
if whence == "set" then pos = offset + 1 | |
elseif whence == "cur" then pos = pos + offset | |
elseif whence == "end" then pos = #contents - offset + 1 | |
else error("bad argument #1 to 'seek' (invalid option '" .. whence .. "')") end | |
return pos - 1 | |
end or nil, | |
close = function() | |
if closed then error("attempt to use a closed file", 2) end | |
closed = true | |
pos = #contents + 1 | |
end | |
} else return { | |
write = function(data) | |
expect(1, data, "string", "number") | |
if closed then error("attempt to use a closed file", 2) end | |
if type(data) == "number" then | |
if isBinary then data = string.char(data) or '?' | |
else data = tostring(data) end | |
end | |
contents = contents:sub(1, pos-1) .. data .. contents:sub(pos + #data) | |
end, | |
writeLine = function(data) | |
expect(1, data, "string", "number") | |
if closed then error("attempt to use a closed file", 2) end | |
if type(data) == "number" then | |
if isBinary then data = string.char(data) or '?' | |
else data = tostring(data) end | |
end | |
data = data .. "\n" | |
contents = contents:sub(1, pos-1) .. data .. contents:sub(pos + #data) | |
end, | |
flush = function() | |
if closed then error("attempt to use a closed file", 2) end | |
local data = "" | |
if not isBinary then for c in contents:gmatch(".") do data = data .. utf8.char(c:byte()) end | |
else data = contents end | |
local iv = getFilePath(path) | |
if iv then iv = {iv:byte(1, 16)} else | |
iv = {} | |
for i = 1, 16 do iv[i] = math.random(0, 255) end | |
end | |
local file = orig_fs.open(sha256(fs.combine(path, "") .. iv2bin(iv)), "wb") | |
file.write(aeslua.encrypt(key, data, 32, aeslua.CBCMODE, iv, true)) | |
file.close() | |
setFilePath(path, iv2bin(iv)) | |
saveFileTree() | |
end, | |
seek = isBinary and function(whence, offset) | |
if closed then error("attempt to use a closed file", 2) end | |
whence = whence or "cur" | |
offset = offset or 0 | |
if whence == "set" then pos = offset + 1 | |
elseif whence == "cur" then pos = pos + offset | |
elseif whence == "end" then pos = #contents - offset + 1 | |
else error("bad argument #1 to 'seek' (invalid option '" .. whence .. "')") end | |
return pos - 1 | |
end or nil, | |
close = function() | |
if closed then error("attempt to use a closed file", 2) end | |
local data = "" | |
if not isBinary then for c in contents:gmatch(".") do data = data .. utf8.char(c:byte()) end | |
else data = contents end | |
local iv = getFilePath(path) | |
if iv then iv = {iv:byte(1, 16)} else | |
iv = {} | |
for i = 1, 16 do iv[i] = math.random(0, 255) end | |
end | |
local file = orig_fs.open(sha256(fs.combine(path, "") .. iv2bin(iv)), "wb") | |
file.write(aeslua.encrypt(key, data, 32, aeslua.CBCMODE, iv, true)) | |
file.close() | |
setFilePath(path, iv2bin(iv)) | |
saveFileTree() | |
closed = true | |
pos = #contents + 1 | |
end | |
} end | |
end | |
local function aux_find(parts, t) | |
t = t or filetree | |
if #parts == 0 then return t elseif type(t) ~= "table" then return nil end | |
local parts2 = {} | |
for i,v in ipairs(parts) do parts2[i] = v end | |
local name = table.remove(parts2, 1) | |
local retval = {} | |
for k, v in pairs(t) do if k:match("^" .. name:gsub("([%%%.])", "%%%1"):gsub("%*", "%.%*") .. "$") then retval[k] = aux_find(parts2, v) end end | |
return retval | |
end | |
local function combineKeys(t, prefix) | |
prefix = prefix or "" | |
if t == nil then return {} end | |
local retval = {} | |
for k,v in pairs(t) do | |
if type(v) == "string" then table.insert(retval, prefix .. k) | |
else for _,w in ipairs(combineKeys(v, prefix .. k .. "/")) do table.insert(retval, w) end end | |
end | |
return retval | |
end | |
function fs.find(wildcard) | |
expect(1, wildcard, "string") | |
local retval = orig_fs.find(wildcard) | |
for _,v in ipairs(combineKeys(aux_find(splitPath(wildcard)))) do table.insert(retval, v) end | |
local keep = {} | |
for _,v in ipairs(retval) do if not isSHA(fs.getName(v)) then table.insert(keep, v) end end | |
retval = keep | |
table.sort(retval) | |
return retval | |
end | |
function fs.attributes(path) | |
expect(1, path, "string") | |
if orig_fs.exists(path) or filetree == nil then return orig_fs.attributes(path) end | |
local data = getFilePath(path) | |
local attr | |
if data == nil then error("/" .. fs.combine(path, "") .. ": No such file", 2) | |
elseif type(data) == "table" then | |
attr = orig_fs.attributes("9f721fc36d10270affc7dbba9594e7665f95e0ad6d1729f5d9c0e6cc18235cf3") | |
attr.isDir = true | |
attr.size = 0 | |
else | |
attr = orig_fs.attributes(sha256(fs.combine(path, "") .. data)) | |
attr.isDir = false | |
attr.size = fs.getSize(path) | |
end | |
return attr | |
end | |
local tEmpty = {} | |
function fs.complete( sPath, sLocation, bIncludeFiles, bIncludeDirs ) | |
if type( sPath ) ~= "string" then | |
error( "bad argument #1 (expected string, got " .. type( sPath ) .. ")", 2 ) | |
end | |
if type( sLocation ) ~= "string" then | |
error( "bad argument #2 (expected string, got " .. type( sLocation ) .. ")", 2 ) | |
end | |
if bIncludeFiles ~= nil and type( bIncludeFiles ) ~= "boolean" then | |
error( "bad argument #3 (expected boolean, got " .. type( bIncludeFiles ) .. ")", 2 ) | |
end | |
if bIncludeDirs ~= nil and type( bIncludeDirs ) ~= "boolean" then | |
error( "bad argument #4 (expected boolean, got " .. type( bIncludeDirs ) .. ")", 2 ) | |
end | |
bIncludeFiles = (bIncludeFiles ~= false) | |
bIncludeDirs = (bIncludeDirs ~= false) | |
local sDir = sLocation | |
local nStart = 1 | |
local nSlash = string.find( sPath, "[/\\]", nStart ) | |
if nSlash == 1 then | |
sDir = "" | |
nStart = 2 | |
end | |
local sName | |
while not sName do | |
local nSlash = string.find( sPath, "[/\\]", nStart ) | |
if nSlash then | |
local sPart = string.sub( sPath, nStart, nSlash - 1 ) | |
sDir = fs.combine( sDir, sPart ) | |
nStart = nSlash + 1 | |
else | |
sName = string.sub( sPath, nStart ) | |
end | |
end | |
if fs.isDir( sDir ) then | |
local tResults = {} | |
if bIncludeDirs and sPath == "" then | |
table.insert( tResults, "." ) | |
end | |
if sDir ~= "" then | |
if sPath == "" then | |
table.insert( tResults, (bIncludeDirs and "..") or "../" ) | |
elseif sPath == "." then | |
table.insert( tResults, (bIncludeDirs and ".") or "./" ) | |
end | |
end | |
local tFiles = fs.list( sDir ) | |
for n=1,#tFiles do | |
local sFile = tFiles[n] | |
if #sFile >= #sName and string.sub( sFile, 1, #sName ) == sName then | |
local bIsDir = fs.isDir( fs.combine( sDir, sFile ) ) | |
local sResult = string.sub( sFile, #sName + 1 ) | |
if bIsDir then | |
table.insert( tResults, sResult .. "/" ) | |
if bIncludeDirs and #sResult > 0 then | |
table.insert( tResults, sResult ) | |
end | |
else | |
if bIncludeFiles and #sResult > 0 then | |
table.insert( tResults, sResult ) | |
end | |
end | |
end | |
end | |
return tResults | |
end | |
return tEmpty | |
end | |
function fs.encrypt(from, to) | |
expect(1, from, "string") | |
expect(2, to, "string") | |
if filetree == nil then error("Cannot encrypt files while locked", 2) | |
elseif not orig_fs.exists(from) then error("/" .. fs.combine(from, "") .. ": No such file", 2) | |
elseif orig_fs.isDir(from) then error("/" .. fs.combine(from, "") .. ": Is a directory", 2) | |
elseif getFilePath(to) ~= nil then error("/" .. fs.combine(to, "") .. ": File exists", 2) end | |
local iv = {} | |
for i = 1, 16 do iv[i] = math.random(0, 255) end | |
local fromfile = orig_fs.open(from, "rb") | |
local tofile = orig_fs.open(sha256(fs.combine(to, "") .. iv2bin(iv)), "wb") | |
tofile.write(aeslua.encrypt(key, fromfile.readAll(), 32, aeslua.CBCMODE, iv, true)) | |
fromfile.close() | |
tofile.close() | |
setFilePath(to, iv2bin(iv)) | |
saveFileTree() | |
end | |
function fs.decrypt(from, to) | |
expect(1, from, "string") | |
expect(2, to, "string") | |
local iv = getFilePath(from) | |
if filetree == nil then error("Cannot decrypt files while locked", 2) | |
elseif iv == nil then error("/" .. fs.combine(from, "") .. ": No such file", 2) | |
elseif type(iv) == "table" then error("/" .. fs.combine(from, "") .. ": Is a directory", 2) | |
elseif orig_fs.exists(to) then error("/" .. fs.combine(to, "") .. ": File exists", 2) end | |
local fromfile = orig_fs.open(sha256(fs.combine(from, "") .. iv), "rb") | |
local tofile = orig_fs.open(to, "wb") | |
tofile.write(aeslua.decrypt(key, fromfile.readAll(), 32, aeslua.CBCMODE, {iv:byte(1, 16)}, true)) | |
fromfile.close() | |
tofile.close() | |
end | |
_G.io = {} | |
do | |
--- Emulates Lua's standard [io library][io]. | |
-- | |
-- [io]: https://www.lua.org/manual/5.1/manual.html#5.7 | |
-- | |
-- @module io | |
local type_of = _G.type | |
--- If we return nil then close the file, as we've reached the end. | |
-- We use this weird wrapper function as we wish to preserve the varargs | |
local function checkResult(handle, ...) | |
if ... == nil and handle._autoclose and not handle._closed then handle:close() end | |
return ... | |
end | |
--- A file handle which can be read or written to. | |
-- | |
-- @type Handle | |
local handleMetatable | |
handleMetatable = { | |
__name = "FILE*", | |
__tostring = function(self) | |
if self._closed then | |
return "file (closed)" | |
else | |
local hash = tostring(self._handle):match("table: (%x+)") | |
return "file (" .. hash .. ")" | |
end | |
end, | |
__index = { | |
--- Close this file handle, freeing any resources it uses. | |
-- | |
-- @treturn[1] true If this handle was successfully closed. | |
-- @treturn[2] nil If this file handle could not be closed. | |
-- @treturn[2] string The reason it could not be closed. | |
-- @throws If this handle was already closed. | |
close = function(self) | |
if type_of(self) ~= "table" or getmetatable(self) ~= handleMetatable then | |
error("bad argument #1 (FILE expected, got " .. type_of(self) .. ")", 2) | |
end | |
if self._closed then error("attempt to use a closed file", 2) end | |
local handle = self._handle | |
if handle.close then | |
self._closed = true | |
handle.close() | |
return true | |
else | |
return nil, "attempt to close standard stream" | |
end | |
end, | |
--- Flush any buffered output, forcing it to be written to the file | |
-- | |
-- @throws If the handle has been closed | |
flush = function(self) | |
if type_of(self) ~= "table" or getmetatable(self) ~= handleMetatable then | |
error("bad argument #1 (FILE expected, got " .. type_of(self) .. ")", 2) | |
end | |
if self._closed then error("attempt to use a closed file", 2) end | |
local handle = self._handle | |
if handle.flush then handle.flush() end | |
return true | |
end, | |
lines = function(self, ...) | |
if type_of(self) ~= "table" or getmetatable(self) ~= handleMetatable then | |
error("bad argument #1 (FILE expected, got " .. type_of(self) .. ")", 2) | |
end | |
if self._closed then error("attempt to use a closed file", 2) end | |
local handle = self._handle | |
if not handle.read then return nil, "file is not readable" end | |
local args = table.pack(...) | |
return function() | |
if self._closed then error("file is already closed", 2) end | |
return checkResult(self, self:read(table.unpack(args, 1, args.n))) | |
end | |
end, | |
read = function(self, ...) | |
if type_of(self) ~= "table" or getmetatable(self) ~= handleMetatable then | |
error("bad argument #1 (FILE expected, got " .. type_of(self) .. ")", 2) | |
end | |
if self._closed then error("attempt to use a closed file", 2) end | |
local handle = self._handle | |
if not handle.read and not handle.readLine then return nil, "Not opened for reading" end | |
local n = select("#", ...) | |
local output = {} | |
for i = 1, n do | |
local arg = select(i, ...) | |
local res | |
if type_of(arg) == "number" then | |
if handle.read then res = handle.read(arg) end | |
elseif type_of(arg) == "string" then | |
local format = arg:gsub("^%*", ""):sub(1, 1) | |
if format == "l" then | |
if handle.readLine then res = handle.readLine() end | |
elseif format == "L" and handle.readLine then | |
if handle.readLine then res = handle.readLine(true) end | |
elseif format == "a" then | |
if handle.readAll then res = handle.readAll() or "" end | |
elseif format == "n" then | |
res = nil -- Skip this format as we can't really handle it | |
else | |
error("bad argument #" .. i .. " (invalid format)", 2) | |
end | |
else | |
error("bad argument #" .. i .. " (expected string, got " .. type_of(arg) .. ")", 2) | |
end | |
output[i] = res | |
if not res then break end | |
end | |
-- Default to "l" if possible | |
if n == 0 and handle.readLine then return handle.readLine() end | |
return table.unpack(output, 1, n) | |
end, | |
seek = function(self, whence, offset) | |
if type_of(self) ~= "table" or getmetatable(self) ~= handleMetatable then | |
error("bad argument #1 (FILE expected, got " .. type_of(self) .. ")", 2) | |
end | |
if self._closed then error("attempt to use a closed file", 2) end | |
local handle = self._handle | |
if not handle.seek then return nil, "file is not seekable" end | |
-- It's a tail call, so error positions are preserved | |
return handle.seek(whence, offset) | |
end, | |
setvbuf = function(self, mode, size) end, | |
--- Write one or more values to the file | |
-- | |
-- @tparam string|number ... The values to write. | |
-- @treturn[1] Handle The current file, allowing chained calls. | |
-- @treturn[2] nil If the file could not be written to. | |
-- @treturn[2] string The error message which occurred while writing. | |
write = function(self, ...) | |
if type_of(self) ~= "table" or getmetatable(self) ~= handleMetatable then | |
error("bad argument #1 (FILE expected, got " .. type_of(self) .. ")", 2) | |
end | |
if self._closed then error("attempt to use a closed file", 2) end | |
local handle = self._handle | |
if not handle.write then return nil, "file is not writable" end | |
for i = 1, select("#", ...) do | |
local arg = select(i, ...) | |
expect(i, arg, "string", "number") | |
handle.write(arg) | |
end | |
return self | |
end, | |
}, | |
} | |
local defaultInput = setmetatable({ | |
_handle = { readLine = _G.read }, | |
}, handleMetatable) | |
local defaultOutput = setmetatable({ | |
_handle = { write = _G.write }, | |
}, handleMetatable) | |
local defaultError = setmetatable({ | |
_handle = { | |
write = function(...) | |
local oldColour | |
if term.isColour() then | |
oldColour = term.getTextColour() | |
term.setTextColour(colors.red) | |
end | |
_G.write(...) | |
if term.isColour() then term.setTextColour(oldColour) end | |
end, | |
}, | |
}, handleMetatable) | |
local currentInput = defaultInput | |
local currentOutput = defaultOutput | |
--- A file handle representing the "standard input". Reading from this | |
-- file will prompt the user for input. | |
io.stdin = defaultInput | |
--- A file handle representing the "standard output". Writing to this | |
-- file will display the written text to the screen. | |
io.stdout = defaultOutput | |
--- A file handle representing the "standard error" stream. | |
-- | |
-- One may use this to display error messages, writing to it will display | |
-- them on the terminal. | |
io.stderr = defaultError | |
--- Closes the provided file handle. | |
-- | |
-- @tparam[opt] Handle file The file handle to close, defaults to the | |
-- current output file. | |
-- | |
-- @see Handle:close | |
-- @see io.output | |
function io.close(file) | |
if file == nil then return currentOutput:close() end | |
if type_of(file) ~= "table" or getmetatable(file) ~= handleMetatable then | |
error("bad argument #1 (FILE expected, got " .. type_of(file) .. ")", 2) | |
end | |
return file:close() | |
end | |
--- Flushes the current output file. | |
-- | |
-- @see Handle:flush | |
-- @see io.output | |
function io.flush() | |
return currentOutput:flush() | |
end | |
--- Get or set the current input file. | |
-- | |
-- @tparam[opt] Handle|string file The new input file, either as a file path or pre-existing handle. | |
-- @treturn Handle The current input file. | |
-- @throws If the provided filename cannot be opened for reading. | |
function io.input(file) | |
if type_of(file) == "string" then | |
local res, err = open(file, "rb") | |
if not res then error(err, 2) end | |
currentInput = res | |
elseif type_of(file) == "table" and getmetatable(file) == handleMetatable then | |
currentInput = file | |
elseif file ~= nil then | |
error("bad fileument #1 (FILE expected, got " .. type_of(file) .. ")", 2) | |
end | |
return currentInput | |
end | |
--- Opens the given file name in read mode and returns an iterator that, | |
-- each time it is called, returns a new line from the file. | |
-- | |
-- This can be used in a for loop to iterate over all lines of a file: | |
-- | |
-- ```lua | |
-- for line in io.lines(filename) do print(line) end | |
-- ``` | |
-- | |
-- Once the end of the file has been reached, @{nil} will be | |
-- returned. The file is automatically closed. | |
-- | |
-- If no file name is given, the @{io.input|current input} will be used | |
-- instead. In this case, the handle is not used. | |
-- | |
-- @tparam[opt] string filename The name of the file to extract lines from | |
-- @param ... The argument to pass to @{Handle:read} for each line. | |
-- @treturn function():string|nil The line iterator. | |
-- @throws If the file cannot be opened for reading | |
-- | |
-- @see Handle:lines | |
-- @see io.input | |
function io.lines(filename, ...) | |
expect(1, filename, "string", "nil") | |
if filename then | |
local ok, err = open(filename, "rb") | |
if not ok then error(err, 2) end | |
-- We set this magic flag to mark this file as being opened by io.lines and so should be | |
-- closed automatically | |
ok._autoclose = true | |
return ok:lines(...) | |
else | |
return currentInput:lines(...) | |
end | |
end | |
--- Open a file with the given mode, either returning a new file handle | |
-- or @{nil}, plus an error message. | |
-- | |
-- The `mode` string can be any of the following: | |
-- - **"r"**: Read mode | |
-- - **"w"**: Write mode | |
-- - **"w"**: Append mode | |
-- | |
-- The mode may also have a `b` at the end, which opens the file in "binary | |
-- mode". This allows you to read binary files, as well as seek within a file. | |
-- | |
-- @tparam string filename The name of the file to open. | |
-- @tparam[opt] string mode The mode to open the file with. This defaults to `rb`. | |
-- @treturn[1] Handle The opened file. | |
-- @treturn[2] nil In case of an error. | |
-- @treturn[2] string The reason the file could not be opened. | |
function io.open(filename, mode) | |
expect(1, filename, "string") | |
expect(2, mode, "string", "nil") | |
local sMode = mode and mode:gsub("%+", "") or "rb" | |
local file, err = fs.open(filename, sMode) | |
if not file then return nil, err end | |
return setmetatable({ _handle = file }, handleMetatable) | |
end | |
--- Get or set the current output file. | |
-- | |
-- @tparam[opt] Handle|string file The new output file, either as a file path or pre-existing handle. | |
-- @treturn Handle The current output file. | |
-- @throws If the provided filename cannot be opened for writing. | |
function io.output(file) | |
if type_of(file) == "string" then | |
local res, err = open(file, "wb") | |
if not res then error(err, 2) end | |
currentOutput = res | |
elseif type_of(file) == "table" and getmetatable(file) == handleMetatable then | |
currentOutput = file | |
elseif file ~= nil then | |
error("bad argument #1 (FILE expected, got " .. type_of(file) .. ")", 2) | |
end | |
return currentOutput | |
end | |
--- Read from the currently opened input file. | |
-- | |
-- This is equivalent to `io.input():read(...)`. See @{Handle:read|the | |
-- documentation} there for full details. | |
-- | |
-- @tparam string ... The formats to read, defaulting to a whole line. | |
-- @treturn (string|nil)... The data read, or @{nil} if nothing can be read. | |
function io.read(...) | |
return currentInput:read(...) | |
end | |
--- Checks whether `handle` is a given file handle, and determine if it is open | |
-- or not. | |
-- | |
-- @param obj The value to check | |
-- @treturn string|nil `"file"` if this is an open file, `"closed file"` if it | |
-- is a closed file handle, or `nil` if not a file handle. | |
function io.type(obj) | |
if type_of(obj) == "table" and getmetatable(obj) == handleMetatable then | |
if obj._closed then | |
return "closed file" | |
else | |
return "file" | |
end | |
end | |
return nil | |
end | |
--- Write to the currently opened output file. | |
-- | |
-- This is equivalent to `io.output():write(...)`. See @{Handle:write|the | |
-- documentation} there for full details. | |
-- | |
-- @tparam string ... The strings to write | |
function io.write(...) | |
return currentOutput:write(...) | |
end | |
end | |
-- Hide the upvalues of the FS library since they could cause data leakage | |
-- This is the most advanced hiding we're doing; more protection can be offered by other tools | |
if debug then | |
local native_getupvalue, native_setupvalue = debug.getupvalue, debug.setupvalue | |
local getupvalue, setupvalue | |
function getupvalue(func, up) | |
if func == getupvalue then return nil end | |
for _,v in pairs(fs) do if func == v then return nil end end | |
return native_getupvalue(func, up) | |
end | |
function setupvalue(func, up, val) | |
if func == setupvalue then return nil end | |
for _,v in pairs(fs) do if func == v then return nil end end | |
return native_setupvalue(func, up, val) | |
end | |
debug.getupvalue = getupvalue | |
debug.setupvalue = setupvalue | |
end | |
fs.unlock() | |
print("FSEncrypt is now loaded.\nThe filesystem is now unlocked.") |
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
if fs.isUnlocked then local a={...}if a[1]=="lock"or a[1]==nil and fs.isUnlocked()then fs.lock()print("The filesystem is now locked.")elseif a[1]=="unlock"or a[1]==nil then fs.unlock()print("The filesystem is now unlocked.")elseif a[1]=="encrypt"then if a[3]==nil then error("Usage: fsencrypt encrypt <infile> <outfile>")end;fs.encrypt(a[2],a[3])print(a[2].." has been encrypted as "..a[3]..".")elseif a[1]=="decrypt"then if a[3]==nil then error("Usage: fsencrypt decrypt <infile> <outfile>")end;fs.decrypt(a[2],a[3])print(a[2].." has been decrypted as "..a[3]..".")elseif a[1]=="help"then print([[ | |
Usage: | |
fsencrypt | |
Toggles lock status. | |
fsencrypt lock | |
Locks access to encrypted files. | |
fsencrypt unlock | |
Unlocks access to encrypted files. | |
fsencrypt encrypt <infile> <outfile> | |
Encrypts a file. | |
fsencrypt decrypt <infile> <outfile> | |
Decrypts a file. | |
fsencrypt help | |
Displays this help.]])end;return end;local b=(function()local function c(d)local e=setmetatable({},{__index=_ENV or getfenv()})if setfenv then setfenv(d,e)end;return d(e)or e end;local bit=c(function(_ENV,...)local f=math.floor;local g,h;h=function(i,j)return f(i%4294967296/2^j)end;g=function(i,j)return i*2^j%4294967296 end;return{bnot=bit.bnot,band=bit.band,bor=bit.bor,bxor=bit.bxor,rshift=h,lshift=g}end)local k=c(function(_ENV,...)local l=bit.bxor;local g=bit.lshift;local m=0x100;local n=0xff;local o=0x11b;local p={}local q={}local function r(s,t)return l(s,t)end;local function u(s,t)return l(s,t)end;local function v(w)if w==1 then return 1 end;local x=n-q[w]return p[x]end;local function y(s,t)if s==0 or t==0 then return 0 end;local x=q[s]+q[t]if x>=n then x=x-n end;return p[x]end;local function z(s,t)if s==0 then return 0 end;local x=q[s]-q[t]if x<0 then x=x+n end;return p[x]end;local function A()for B=1,m do print("log(",B-1,")=",q[B-1])end end;local function C()for B=1,m do print("exp(",B-1,")=",p[B-1])end end;local function D()local i=1;for B=0,n-1 do p[B]=i;q[i]=B;i=l(g(i,1),i)if i>n then i=u(i,o)end end end;D()return{add=r,sub=u,invert=v,mul=y,div=z,printLog=A,printExp=C}end)local E=c(function(_ENV,...)local l=bit.bxor;local h=bit.rshift;local F=bit.band;local g=bit.lshift;local G;local function H(I)I=l(I,h(I,4))I=l(I,h(I,2))I=l(I,h(I,1))return F(I,1)end;local function J(K,L)if L==0 then return F(K,0xff)else return F(h(K,L*8),0xff)end end;local function M(K,L)if L==0 then return F(K,0xff)else return g(F(K,0xff),L*8)end end;local function N(O,P,m)local Q={}for B=0,m-1 do Q[B+1]=M(O[P+B*4],3)+M(O[P+B*4+1],2)+M(O[P+B*4+2],1)+M(O[P+B*4+3],0)if m%10000==0 then G()end end;return Q end;local function R(Q,S,T,m)m=m or#Q;for B=0,m-1 do for U=0,3 do S[T+B*4+3-U]=J(Q[B+1],U)end;if m%10000==0 then G()end end;return S end;local function V(O)local W=""for B,I in ipairs(O)do W=W..string.format("%02x ",I)end;return W end;local function X(O)local Y={}for B=1,#O,2 do Y[#Y+1]=tonumber(O:sub(B,B+1),16)end;return Y end;local function Z(_)local type=type(_)if type=="number"then return string.format("%08x",_)elseif type=="table"then return V(_)elseif type=="string"then local O={string.byte(_,1,#_)}return V(O)else return _ end end;local function a0(_)local a1=#_;local a2=math.random(0,255)local a3=math.random(0,255)local a4=string.char(a2,a3,a2,a3,J(a1,3),J(a1,2),J(a1,1),J(a1,0))_=a4 .._;local a5=math.ceil(#_/16)*16-#_;local a6=""for B=1,a5 do a6=a6 ..string.char(math.random(0,255))end;return _..a6 end;local function a7(_)local a8={string.byte(_,1,4)}if a8[1]==a8[3]and a8[2]==a8[4]then return true end;return false end;local function a9(_)if not a7(_)then return nil end;local a1=M(string.byte(_,5),3)+M(string.byte(_,6),2)+M(string.byte(_,7),1)+M(string.byte(_,8),0)return string.sub(_,9,8+a1)end;local function aa(_,ab)for B=1,16 do _[B]=l(_[B],ab[B])end end;local function ac(_)local B=16;while true do local ad=_[B]+1;if ad>=256 then _[B]=ad-256;B=(B-2)%16+1 else _[B]=ad;break end end end;local ae,af,ag=os.queueEvent,coroutine.yield,os.time;local ah=ag()function G()local ai=ag()if ai-ah>=0.03 then ah=ai;ae("sleep")af("sleep")end end;local function aj(O)local ak,a8,al,am=string.char,math.random,G,table.insert;local an={}for B=1,O do am(an,a8(0,255))if B%10240==0 then al()end end;return an end;local function ao(O)local ak,a8,al,am=string.char,math.random,G,table.insert;local an={}for B=1,O do am(an,ak(a8(0,255)))if B%10240==0 then al()end end;return table.concat(an)end;return{byteParity=H,getByte=J,putByte=M,bytesToInts=N,intsToBytes=R,bytesToHex=V,hexToBytes=X,toHexString=Z,padByteString=a0,properlyDecrypted=a7,unpadByteString=a9,xorIV=aa,increment=ac,sleepCheckIn=G,getRandomData=aj,getRandomString=ao}end)local ap=c(function(_ENV,...)local M=E.putByte;local J=E.getByte;local aq='rounds'local ar="type"local as=1;local at=2;local au={}local av={}local aw={}local ax={}local ay={}local az={}local aA={}local aB={}local aC={}local aD={}local aE={0x01000000,0x02000000,0x04000000,0x08000000,0x10000000,0x20000000,0x40000000,0x80000000,0x1b000000,0x36000000,0x6c000000,0xd8000000,0xab000000,0x4d000000,0x9a000000,0x2f000000}local function aF(I)local aG=0xf8;local an=0;for B=1,8 do an=bit.lshift(an,1)local aH=E.byteParity(bit.band(I,aG))an=an+aH;local aI=bit.band(aG,1)aG=bit.band(bit.rshift(aG,1),0xff)if aI~=0 then aG=bit.bor(aG,0x80)else aG=bit.band(aG,0x7f)end end;return bit.bxor(an,0x63)end;local function aJ()for B=0,255 do local aK;if B~=0 then aK=k.invert(B)else aK=B end;local aL=aF(aK)au[B]=aL;av[aL]=B end end;local function aM()for aN=0,255 do local I=au[aN]aw[aN]=M(k.mul(0x03,I),0)+M(I,1)+M(I,2)+M(k.mul(0x02,I),3)ax[aN]=M(I,0)+M(I,1)+M(k.mul(0x02,I),2)+M(k.mul(0x03,I),3)ay[aN]=M(I,0)+M(k.mul(0x02,I),1)+M(k.mul(0x03,I),2)+M(I,3)az[aN]=M(k.mul(0x02,I),0)+M(k.mul(0x03,I),1)+M(I,2)+M(I,3)end end;local function aO()for aN=0,255 do local I=av[aN]aA[aN]=M(k.mul(0x0b,I),0)+M(k.mul(0x0d,I),1)+M(k.mul(0x09,I),2)+M(k.mul(0x0e,I),3)aB[aN]=M(k.mul(0x0d,I),0)+M(k.mul(0x09,I),1)+M(k.mul(0x0e,I),2)+M(k.mul(0x0b,I),3)aC[aN]=M(k.mul(0x09,I),0)+M(k.mul(0x0e,I),1)+M(k.mul(0x0b,I),2)+M(k.mul(0x0d,I),3)aD[aN]=M(k.mul(0x0e,I),0)+M(k.mul(0x0b,I),1)+M(k.mul(0x0d,I),2)+M(k.mul(0x09,I),3)end end;local function aP(aQ)local aR=bit.band(aQ,0xff000000)return bit.lshift(aQ,8)+bit.rshift(aR,24)end;local function aS(aQ)return M(au[J(aQ,0)],0)+M(au[J(aQ,1)],1)+M(au[J(aQ,2)],2)+M(au[J(aQ,3)],3)end;local function aT(aU)local aV={}local aW=math.floor(#aU/4)if aW~=4 and aW~=6 and aW~=8 or aW*4~=#aU then error("Invalid key size: "..tostring(aW))return nil end;aV[aq]=aW+6;aV[ar]=as;for B=0,aW-1 do aV[B]=M(aU[B*4+1],3)+M(aU[B*4+2],2)+M(aU[B*4+3],1)+M(aU[B*4+4],0)end;for B=aW,(aV[aq]+1)*4-1 do local aR=aV[B-1]if B%aW==0 then aR=aP(aR)aR=aS(aR)local L=math.floor(B/aW)aR=bit.bxor(aR,aE[L])elseif aW>6 and B%aW==4 then aR=aS(aR)end;aV[B]=bit.bxor(aV[B-aW],aR)end;return aV end;local function aX(aQ)local aY=J(aQ,3)local aZ=J(aQ,2)local a_=J(aQ,1)local b0=J(aQ,0)return M(k.add(k.add(k.add(k.mul(0x0b,aZ),k.mul(0x0d,a_)),k.mul(0x09,b0)),k.mul(0x0e,aY)),3)+M(k.add(k.add(k.add(k.mul(0x0b,a_),k.mul(0x0d,b0)),k.mul(0x09,aY)),k.mul(0x0e,aZ)),2)+M(k.add(k.add(k.add(k.mul(0x0b,b0),k.mul(0x0d,aY)),k.mul(0x09,aZ)),k.mul(0x0e,a_)),1)+M(k.add(k.add(k.add(k.mul(0x0b,aY),k.mul(0x0d,aZ)),k.mul(0x09,a_)),k.mul(0x0e,b0)),0)end;local function b1(aQ)local aY=J(aQ,3)local aZ=J(aQ,2)local a_=J(aQ,1)local b0=J(aQ,0)local b2=bit.bxor(b0,a_)local b3=bit.bxor(aZ,aY)local b4=bit.bxor(b2,b3)b4=bit.bxor(b4,k.mul(0x08,b4))local b5=bit.bxor(b4,k.mul(0x04,bit.bxor(a_,aY)))b4=bit.bxor(b4,k.mul(0x04,bit.bxor(b0,aZ)))return M(bit.bxor(bit.bxor(b0,b4),k.mul(0x02,bit.bxor(aY,b0))),0)+M(bit.bxor(bit.bxor(a_,b5),k.mul(0x02,b2)),1)+M(bit.bxor(bit.bxor(aZ,b4),k.mul(0x02,bit.bxor(aY,b0))),2)+M(bit.bxor(bit.bxor(aY,b5),k.mul(0x02,b3)),3)end;local function b6(aU)local aV=aT(aU)if aV==nil then return nil end;aV[ar]=at;for B=4,(aV[aq]+1)*4-5 do aV[B]=aX(aV[B])end;return aV end;local function b7(b8,aU,b9)for B=0,3 do b8[B+1]=bit.bxor(b8[B+1],aU[b9*4+B])end end;local function ba(bb,bc)bc[1]=bit.bxor(bit.bxor(bit.bxor(aw[J(bb[1],3)],ax[J(bb[2],2)]),ay[J(bb[3],1)]),az[J(bb[4],0)])bc[2]=bit.bxor(bit.bxor(bit.bxor(aw[J(bb[2],3)],ax[J(bb[3],2)]),ay[J(bb[4],1)]),az[J(bb[1],0)])bc[3]=bit.bxor(bit.bxor(bit.bxor(aw[J(bb[3],3)],ax[J(bb[4],2)]),ay[J(bb[1],1)]),az[J(bb[2],0)])bc[4]=bit.bxor(bit.bxor(bit.bxor(aw[J(bb[4],3)],ax[J(bb[1],2)]),ay[J(bb[2],1)]),az[J(bb[3],0)])end;local function bd(bb,bc)bc[1]=M(au[J(bb[1],3)],3)+M(au[J(bb[2],2)],2)+M(au[J(bb[3],1)],1)+M(au[J(bb[4],0)],0)bc[2]=M(au[J(bb[2],3)],3)+M(au[J(bb[3],2)],2)+M(au[J(bb[4],1)],1)+M(au[J(bb[1],0)],0)bc[3]=M(au[J(bb[3],3)],3)+M(au[J(bb[4],2)],2)+M(au[J(bb[1],1)],1)+M(au[J(bb[2],0)],0)bc[4]=M(au[J(bb[4],3)],3)+M(au[J(bb[1],2)],2)+M(au[J(bb[2],1)],1)+M(au[J(bb[3],0)],0)end;local function be(bb,bc)bc[1]=bit.bxor(bit.bxor(bit.bxor(aA[J(bb[1],3)],aB[J(bb[4],2)]),aC[J(bb[3],1)]),aD[J(bb[2],0)])bc[2]=bit.bxor(bit.bxor(bit.bxor(aA[J(bb[2],3)],aB[J(bb[1],2)]),aC[J(bb[4],1)]),aD[J(bb[3],0)])bc[3]=bit.bxor(bit.bxor(bit.bxor(aA[J(bb[3],3)],aB[J(bb[2],2)]),aC[J(bb[1],1)]),aD[J(bb[4],0)])bc[4]=bit.bxor(bit.bxor(bit.bxor(aA[J(bb[4],3)],aB[J(bb[3],2)]),aC[J(bb[2],1)]),aD[J(bb[1],0)])end;local function bf(bb,bc)bc[1]=M(av[J(bb[1],3)],3)+M(av[J(bb[4],2)],2)+M(av[J(bb[3],1)],1)+M(av[J(bb[2],0)],0)bc[2]=M(av[J(bb[2],3)],3)+M(av[J(bb[1],2)],2)+M(av[J(bb[4],1)],1)+M(av[J(bb[3],0)],0)bc[3]=M(av[J(bb[3],3)],3)+M(av[J(bb[2],2)],2)+M(av[J(bb[1],1)],1)+M(av[J(bb[4],0)],0)bc[4]=M(av[J(bb[4],3)],3)+M(av[J(bb[3],2)],2)+M(av[J(bb[2],1)],1)+M(av[J(bb[1],0)],0)end;local function bg(aU,bh,bi,S,T)bi=bi or 1;S=S or{}T=T or 1;local b8={}local bj={}if aU[ar]~=as then error("No encryption key: "..tostring(aU[ar])..", expected "..as)return end;b8=E.bytesToInts(bh,bi,4)b7(b8,aU,0)local b9=1;while b9<aU[aq]-1 do ba(b8,bj)b7(bj,aU,b9)b9=b9+1;ba(bj,b8)b7(b8,aU,b9)b9=b9+1 end;ba(b8,bj)b7(bj,aU,b9)b9=b9+1;bd(bj,b8)b7(b8,aU,b9)E.sleepCheckIn()return E.intsToBytes(b8,S,T)end;local function bk(aU,bh,bi,S,T)bi=bi or 1;S=S or{}T=T or 1;local b8={}local bj={}if aU[ar]~=at then error("No decryption key: "..tostring(aU[ar]))return end;b8=E.bytesToInts(bh,bi,4)b7(b8,aU,aU[aq])local b9=aU[aq]-1;while b9>2 do be(b8,bj)b7(bj,aU,b9)b9=b9-1;be(bj,b8)b7(b8,aU,b9)b9=b9-1 end;be(b8,bj)b7(bj,aU,b9)b9=b9-1;bf(bj,b8)b7(b8,aU,b9)E.sleepCheckIn()return E.intsToBytes(b8,S,T)end;aJ()aM()aO()return{ROUNDS=aq,KEY_TYPE=ar,ENCRYPTION_KEY=as,DECRYPTION_KEY=at,expandEncryptionKey=aT,expandDecryptionKey=b6,encrypt=bg,decrypt=bk}end)local bl=c(function(_ENV,...)local function bm()return{}end;local function bn(bo,bp)table.insert(bo,bp)end;local function bq(bo)return table.concat(bo)end;return{new=bm,addString=bn,toString=bq}end)local br=c(function(_ENV,...)local bs={}local a8=math.random;function bs.encryptString(aU,_,bt,ab)if ab then local bu={}for B=1,16 do bu[B]=ab[B]end;ab=bu else ab={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}end;local bv=ap.expandEncryptionKey(aU)local bw=bl.new()for B=1,#_/16 do local bx=(B-1)*16+1;local by={string.byte(_,bx,bx+15)}ab=bt(bv,by,ab)bl.addString(bw,string.char(unpack(by)))end;return bl.toString(bw)end;function bs.encryptECB(bv,by,ab)ap.encrypt(bv,by,1,by,1)end;function bs.encryptCBC(bv,by,ab)E.xorIV(by,ab)ap.encrypt(bv,by,1,by,1)return by end;function bs.encryptOFB(bv,by,ab)ap.encrypt(bv,ab,1,ab,1)E.xorIV(by,ab)return ab end;function bs.encryptCFB(bv,by,ab)ap.encrypt(bv,ab,1,ab,1)E.xorIV(by,ab)return by end;function bs.encryptCTR(bv,by,ab)local bz={}for U=1,16 do bz[U]=ab[U]end;ap.encrypt(bv,ab,1,ab,1)E.xorIV(by,ab)E.increment(bz)return bz end;function bs.decryptString(aU,_,bt,ab)if ab then local bu={}for B=1,16 do bu[B]=ab[B]end;ab=bu else ab={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}end;local bv;if bt==bs.decryptOFB or bt==bs.decryptCFB or bt==bs.decryptCTR then bv=ap.expandEncryptionKey(aU)else bv=ap.expandDecryptionKey(aU)end;local bA=bl.new()for B=1,#_/16 do local bx=(B-1)*16+1;local by={string.byte(_,bx,bx+15)}ab=bt(bv,by,ab)bl.addString(bA,string.char(unpack(by)))end;return bl.toString(bA)end;function bs.decryptECB(bv,by,ab)ap.decrypt(bv,by,1,by,1)return ab end;function bs.decryptCBC(bv,by,ab)local bz={}for U=1,16 do bz[U]=by[U]end;ap.decrypt(bv,by,1,by,1)E.xorIV(by,ab)return bz end;function bs.decryptOFB(bv,by,ab)ap.encrypt(bv,ab,1,ab,1)E.xorIV(by,ab)return ab end;function bs.decryptCFB(bv,by,ab)local bz={}for U=1,16 do bz[U]=by[U]end;ap.encrypt(bv,ab,1,ab,1)E.xorIV(by,ab)return bz end;bs.decryptCTR=bs.encryptCTR;return bs end)local bB={AES128=16,AES192=24,AES256=32,ECBMODE=1,CBCMODE=2,OFBMODE=3,CFBMODE=4,CTRMODE=4}local function bC(bD,bE,ab)local bF=bE;if bE==bB.AES192 then bF=32 end;if bF>#bD then local bG=""for B=1,bF-#bD do bG=bG..string.char(0)end;bD=bD..bG else bD=string.sub(bD,1,bF)end;local bH={string.byte(bD,1,#bD)}bD=br.encryptString(bH,bD,br.encryptCBC,ab)bD=string.sub(bD,1,bE)return{string.byte(bD,1,#bD)}end;function bB.encrypt(bD,_,bE,bI,ab,bJ)assert(bD~=nil,"Empty password.")assert(bD~=nil,"Empty data.")local bI=bI or bB.CBCMODE;local bE=bE or bB.AES128;local aU=bJ and{bD:byte(1,bE)}or bC(bD,bE,ab)local bK=E.padByteString(_)if bI==bB.ECBMODE then return br.encryptString(aU,bK,br.encryptECB,ab)elseif bI==bB.CBCMODE then return br.encryptString(aU,bK,br.encryptCBC,ab)elseif bI==bB.OFBMODE then return br.encryptString(aU,bK,br.encryptOFB,ab)elseif bI==bB.CFBMODE then return br.encryptString(aU,bK,br.encryptCFB,ab)elseif bI==bB.CTRMODE then return br.encryptString(aU,bK,br.encryptCTR,ab)else error("Unknown mode",2)end end;function bB.decrypt(bD,_,bE,bI,ab,bJ)local bI=bI or bB.CBCMODE;local bE=bE or bB.AES128;local aU=bJ and{bD:byte(1,bE)}or bC(bD,bE,ab)local bL;if bI==bB.ECBMODE then bL=br.decryptString(aU,_,br.decryptECB,ab)elseif bI==bB.CBCMODE then bL=br.decryptString(aU,_,br.decryptCBC,ab)elseif bI==bB.OFBMODE then bL=br.decryptString(aU,_,br.decryptOFB,ab)elseif bI==bB.CFBMODE then bL=br.decryptString(aU,_,br.decryptCFB,ab)elseif bI==bB.CTRMODE then bL=br.decryptString(aU,_,br.decryptCTR,ab)else error("Unknown mode",2)end;return E.unpadByteString(bL)end;return bB end)()local bM=(function()local bN=false;local unpack,bO,I,ak,bP,u,bQ,bR,bS,f,bT,bU,bV,tonumber,type=table.unpack or unpack,table.concat,string.byte,string.char,string.rep,string.sub,string.gsub,string.gmatch,string.format,math.floor,math.ceil,math.min,math.max,tonumber,type;local function bW(bX)local bY,m,bZ,b_=0,bX,bX;while true do bY,b_,m,bZ=bY+1,m,m+m+1,bZ+bZ+bY%2;if bY>256 or m-(m-1)~=1 or bZ-(bZ-1)~=1 or m==bZ then return bY,false elseif m==b_ then return bY,true end end end;local aN=2/3;local c0=aN*5>3 and aN*4<3 and bW(1.0)>=53;assert(c0,"at least 53-bit floating point numbers are required")local c1,c2=bW(1)local c3=c2 and c1==64;local c4=c2 and c1==32;assert(c3 or c4 or not c2,"Lua integers must be either 32-bit or 64-bit")local c5=({false,[1]=true})[1]and(type(jit)~="table"or jit.version_num>=20000)local c6;local c7;local c8;local c9;local ca;if c5 then c9=require"bit"ca="bit"local cb,an=pcall(require,"ffi")if cb then c8=an end;c6=not not loadstring"b=0b0"c7=type(jit)=="table"and jit.arch or c8 and c8.arch or nil else for cc,cd in ipairs((_VERSION=="Lua 5.2"or type(_HOST)=="string")and{"bit32","bit"}or{"bit","bit32"})do if type(_G[cd])=="table"and _G[cd].bxor then c9=_G[cd]ca=cd;break end end end;if bN then print("Abilities:")print(" Lua version: "..(c5 and"LuaJIT "..(c6 and"2.1 "or"2.0 ")..(c7 or"")..(c8 and" with FFI"or" without FFI")or _VERSION))print(" Integer bitwise operators: "..(c3 and"int64"or c4 and"int32"or"no"))print(" 32-bit bitwise library: "..(ca or"not found"))end;local ce,cf;if c5 and c8 then ce="Using 'ffi' library of LuaJIT"cf="FFI"elseif c5 then ce="Using special code for FFI-less LuaJIT"cf="LJ"elseif c3 then ce="Using native int64 bitwise operators"cf="INT64"elseif c4 then ce="Using native int32 bitwise operators"cf="INT32"elseif ca then ce="Using '"..ca.."' library"cf="LIB32"else ce="Emulating bitwise operators using look-up table"cf="EMUL"end;if bN then print("Implementation selected:")print(" "..ce)end;local cg,ch,ci,cj,ck,cl,cm,cn,co,cp,cq;if cf=="FFI"or cf=="LJ"or cf=="LIB32"then cg=c9.band;ch=c9.bor;ci=c9.bxor;cj=c9.lshift;ck=c9.rshift;cl=c9.rol or c9.lrotate;cm=c9.ror or c9.rrotate;cn=c9.bnot;co=c9.tobit;cp=c9.tohex;assert(cg and ch and ci and cj and ck and cl and cm and cn,"Library '"..ca.."' is incomplete")cq=ci elseif cf=="EMUL"then function cj(aN,m)return aN*2^m%2^32 end;function ck(aN,m)aN=aN%2^32/2^m;return aN-aN%1 end;function cl(aN,m)aN=aN%2^32*2^m;local cr=aN%2^32;return cr+(aN-cr)/2^32 end;function cm(aN,m)aN=aN%2^32/2^m;local cr=aN%1;return cr*2^32+aN-cr end;local cs={[0]=0}local ct=0;for cu=0,127*256,256 do for aN=cu,cu+127 do aN=cs[aN]*2;cs[ct]=aN;cs[ct+1]=aN;cs[ct+256]=aN;cs[ct+257]=aN+1;ct=ct+2 end;ct=ct+256 end;local function cv(aN,cu,cw)local cx=aN%2^32;local cy=cu%2^32;local cz=cx%256;local cA=cy%256;local cB=cs[cz+cA*256]aN=cx-cz;cu=(cy-cA)/256;cz=aN%65536;cA=cu%256;cB=cB+cs[cz+cA]*256;aN=(aN-cz)/256;cu=(cu-cA)/256;cz=aN%65536+cu%256;cB=cB+cs[cz]*65536;cB=cB+cs[(aN+cu-cz)/256]*16777216;if cw then cB=cx+cy-cw*cB end;return cB end;function cg(aN,cu)return cv(aN,cu)end;function ch(aN,cu)return cv(aN,cu,1)end;function ci(aN,cu,cC,b2,b3)if cC then if b2 then if b3 then b2=cv(b2,b3,2)end;cC=cv(cC,b2,2)end;cu=cv(cu,cC,2)end;return cv(aN,cu,2)end;function cq(aN,cu)return aN+cu-2*cs[aN+cu*256]end end;cp=cp or pcall(bS,"%x",2^31)and function(aN)return bS("%08x",aN%4294967296)end or function(aN)return bS("%08x",(aN+2^31)%2^32-2^31)end;local function cD(aN)return ci(aN,0xA5A5A5A5)%4294967296 end;local function cE()return{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}end;local cF,cG,cH,cI,cJ;local cK,cL,cM,cN,cO,cP={},{},{},{},{},{}local cQ={[224]={},[256]=cN}local cR,cS={[384]={},[512]=cM},{[384]={},[512]=cN}local cT,cU={},{0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476,0xC3D2E1F0}local cV={0,0,0,0,0,0,0,0,28,25,26,27,0,0,10,9,11,12,0,15,16,17,18,0,20,22,23,21}local cW,cX,cY;local cZ={}local c_,d0,d1=4294967296,0,0;local function d2(d3)local d4={}for cc,d5 in ipairs{1,9,13,17,18,21}do d4[d5]="<"..bP(d3,d5)end;return d4 end;if cf=="FFI"then local d6=c8.new"int32_t[80]"function cF(d7,d8,d9,d5)local da,db=d6,cL;for dc=d9,d9+d5-1,64 do for U=0,15 do dc=dc+4;local i,c9,dd,de=I(d8,dc-3,dc)da[U]=ch(cj(i,24),cj(c9,16),cj(dd,8),de)end;for U=16,63 do local i,c9=da[U-15],da[U-2]da[U]=co(ci(cm(i,7),cl(i,14),ck(i,3))+ci(cl(c9,15),cl(c9,13),ck(c9,10))+da[U-7]+da[U-16])end;local i,c9,dd,de,e,d,df,dg=d7[1],d7[2],d7[3],d7[4],d7[5],d7[6],d7[7],d7[8]for U=0,63,8 do local cC=co(ci(df,cg(e,ci(d,df)))+ci(cm(e,6),cm(e,11),cl(e,7))+da[U]+db[U+1]+dg)dg,df,d,e=df,d,e,co(de+cC)de,dd,c9,i=dd,c9,i,co(ci(cg(i,ci(c9,dd)),cg(c9,dd))+ci(cm(i,2),cm(i,13),cl(i,10))+cC)cC=co(ci(df,cg(e,ci(d,df)))+ci(cm(e,6),cm(e,11),cl(e,7))+da[U+1]+db[U+2]+dg)dg,df,d,e=df,d,e,co(de+cC)de,dd,c9,i=dd,c9,i,co(ci(cg(i,ci(c9,dd)),cg(c9,dd))+ci(cm(i,2),cm(i,13),cl(i,10))+cC)cC=co(ci(df,cg(e,ci(d,df)))+ci(cm(e,6),cm(e,11),cl(e,7))+da[U+2]+db[U+3]+dg)dg,df,d,e=df,d,e,co(de+cC)de,dd,c9,i=dd,c9,i,co(ci(cg(i,ci(c9,dd)),cg(c9,dd))+ci(cm(i,2),cm(i,13),cl(i,10))+cC)cC=co(ci(df,cg(e,ci(d,df)))+ci(cm(e,6),cm(e,11),cl(e,7))+da[U+3]+db[U+4]+dg)dg,df,d,e=df,d,e,co(de+cC)de,dd,c9,i=dd,c9,i,co(ci(cg(i,ci(c9,dd)),cg(c9,dd))+ci(cm(i,2),cm(i,13),cl(i,10))+cC)cC=co(ci(df,cg(e,ci(d,df)))+ci(cm(e,6),cm(e,11),cl(e,7))+da[U+4]+db[U+5]+dg)dg,df,d,e=df,d,e,co(de+cC)de,dd,c9,i=dd,c9,i,co(ci(cg(i,ci(c9,dd)),cg(c9,dd))+ci(cm(i,2),cm(i,13),cl(i,10))+cC)cC=co(ci(df,cg(e,ci(d,df)))+ci(cm(e,6),cm(e,11),cl(e,7))+da[U+5]+db[U+6]+dg)dg,df,d,e=df,d,e,co(de+cC)de,dd,c9,i=dd,c9,i,co(ci(cg(i,ci(c9,dd)),cg(c9,dd))+ci(cm(i,2),cm(i,13),cl(i,10))+cC)cC=co(ci(df,cg(e,ci(d,df)))+ci(cm(e,6),cm(e,11),cl(e,7))+da[U+6]+db[U+7]+dg)dg,df,d,e=df,d,e,co(de+cC)de,dd,c9,i=dd,c9,i,co(ci(cg(i,ci(c9,dd)),cg(c9,dd))+ci(cm(i,2),cm(i,13),cl(i,10))+cC)cC=co(ci(df,cg(e,ci(d,df)))+ci(cm(e,6),cm(e,11),cl(e,7))+da[U+7]+db[U+8]+dg)dg,df,d,e=df,d,e,co(de+cC)de,dd,c9,i=dd,c9,i,co(ci(cg(i,ci(c9,dd)),cg(c9,dd))+ci(cm(i,2),cm(i,13),cl(i,10))+cC)end;d7[1],d7[2],d7[3],d7[4]=co(i+d7[1]),co(c9+d7[2]),co(dd+d7[3]),co(de+d7[4])d7[5],d7[6],d7[7],d7[8]=co(e+d7[5]),co(d+d7[6]),co(df+d7[7]),co(dg+d7[8])end end;local dh=c8.new"int64_t[80]"local di=c8.typeof"int64_t"local dj=c8.typeof"int32_t"local dk=c8.typeof"uint32_t"d0=di(2^32)if c6 then local dl,dm,dn,dp,dq,dr,ds,dt=cg,ch,ci,cn,cj,ck,cl,cm;cW=cp;local du=c8.typeof"int64_t[30]"cY=0;d1=di(2^32)function cE()return du()end;function cJ(dv,cc,d8,d9,d5,dw)local dx=cO;local dy=ck(dw,3)for dc=d9,d9+d5-1,dw do for U=0,dy-1 do dc=dc+8;local dg,df,d,e,de,dd,c9,i=I(d8,dc-7,dc)dv[U]=dn(dv[U],dm(ch(cj(i,24),cj(c9,16),cj(dd,8),de)*di(2^32),dk(dj(ch(cj(e,24),cj(d,16),cj(df,8),dg)))))end;for dz=1,24 do for U=0,4 do dv[25+U]=dn(dv[U],dv[U+5],dv[U+10],dv[U+15],dv[U+20])end;local dA=dn(dv[25],ds(dv[27],1))dv[1],dv[6],dv[11],dv[16]=ds(dn(dA,dv[6]),44),ds(dn(dA,dv[16]),45),ds(dn(dA,dv[1]),1),ds(dn(dA,dv[11]),10)dv[21]=ds(dn(dA,dv[21]),2)dA=dn(dv[26],ds(dv[28],1))dv[2],dv[7],dv[12],dv[22]=ds(dn(dA,dv[12]),43),ds(dn(dA,dv[22]),61),ds(dn(dA,dv[7]),6),ds(dn(dA,dv[2]),62)dv[17]=ds(dn(dA,dv[17]),15)dA=dn(dv[27],ds(dv[29],1))dv[3],dv[8],dv[18],dv[23]=ds(dn(dA,dv[18]),21),ds(dn(dA,dv[3]),28),ds(dn(dA,dv[23]),56),ds(dn(dA,dv[8]),55)dv[13]=ds(dn(dA,dv[13]),25)dA=dn(dv[28],ds(dv[25],1))dv[4],dv[14],dv[19],dv[24]=ds(dn(dA,dv[24]),14),ds(dn(dA,dv[19]),8),ds(dn(dA,dv[4]),27),ds(dn(dA,dv[14]),39)dv[9]=ds(dn(dA,dv[9]),20)dA=dn(dv[29],ds(dv[26],1))dv[5],dv[10],dv[15],dv[20]=ds(dn(dA,dv[10]),3),ds(dn(dA,dv[20]),18),ds(dn(dA,dv[5]),36),ds(dn(dA,dv[15]),41)dv[0]=dn(dA,dv[0])dv[0],dv[1],dv[2],dv[3],dv[4]=dn(dv[0],dl(dp(dv[1]),dv[2]),dx[dz]),dn(dv[1],dl(dp(dv[2]),dv[3])),dn(dv[2],dl(dp(dv[3]),dv[4])),dn(dv[3],dl(dp(dv[4]),dv[0])),dn(dv[4],dl(dp(dv[0]),dv[1]))dv[5],dv[6],dv[7],dv[8],dv[9]=dn(dv[8],dl(dp(dv[9]),dv[5])),dn(dv[9],dl(dp(dv[5]),dv[6])),dn(dv[5],dl(dp(dv[6]),dv[7])),dn(dv[6],dl(dp(dv[7]),dv[8])),dn(dv[7],dl(dp(dv[8]),dv[9]))dv[10],dv[11],dv[12],dv[13],dv[14]=dn(dv[11],dl(dp(dv[12]),dv[13])),dn(dv[12],dl(dp(dv[13]),dv[14])),dn(dv[13],dl(dp(dv[14]),dv[10])),dn(dv[14],dl(dp(dv[10]),dv[11])),dn(dv[10],dl(dp(dv[11]),dv[12]))dv[15],dv[16],dv[17],dv[18],dv[19]=dn(dv[19],dl(dp(dv[15]),dv[16])),dn(dv[15],dl(dp(dv[16]),dv[17])),dn(dv[16],dl(dp(dv[17]),dv[18])),dn(dv[17],dl(dp(dv[18]),dv[19])),dn(dv[18],dl(dp(dv[19]),dv[15]))dv[20],dv[21],dv[22],dv[23],dv[24]=dn(dv[22],dl(dp(dv[23]),dv[24])),dn(dv[23],dl(dp(dv[24]),dv[20])),dn(dv[24],dl(dp(dv[20]),dv[21])),dn(dv[20],dl(dp(dv[21]),dv[22])),dn(dv[21],dl(dp(dv[22]),dv[23]))end end end;local dB=0xA5A5A5A5*di(2^32+1)function cX(dC)return dn(dC,dB)end;function cG(d7,cc,d8,d9,d5)local da,db=dh,cK;for dc=d9,d9+d5-1,128 do for U=0,15 do dc=dc+8;local i,c9,dd,de,e,d,df,dg=I(d8,dc-7,dc)da[U]=dm(ch(cj(i,24),cj(c9,16),cj(dd,8),de)*di(2^32),dk(dj(ch(cj(e,24),cj(d,16),cj(df,8),dg))))end;for U=16,79 do local i,c9=da[U-15],da[U-2]da[U]=dn(dt(i,1),dt(i,8),dr(i,7))+dn(dt(c9,19),ds(c9,3),dr(c9,6))+da[U-7]+da[U-16]end;local i,c9,dd,de,e,d,df,dg=d7[1],d7[2],d7[3],d7[4],d7[5],d7[6],d7[7],d7[8]for U=0,79,8 do local cC=dn(dt(e,14),dt(e,18),ds(e,23))+dn(df,dl(e,dn(d,df)))+dg+db[U+1]+da[U]dg,df,d,e=df,d,e,cC+de;de,dd,c9,i=dd,c9,i,dn(dl(dn(i,c9),dd),dl(i,c9))+dn(dt(i,28),ds(i,25),ds(i,30))+cC;cC=dn(dt(e,14),dt(e,18),ds(e,23))+dn(df,dl(e,dn(d,df)))+dg+db[U+2]+da[U+1]dg,df,d,e=df,d,e,cC+de;de,dd,c9,i=dd,c9,i,dn(dl(dn(i,c9),dd),dl(i,c9))+dn(dt(i,28),ds(i,25),ds(i,30))+cC;cC=dn(dt(e,14),dt(e,18),ds(e,23))+dn(df,dl(e,dn(d,df)))+dg+db[U+3]+da[U+2]dg,df,d,e=df,d,e,cC+de;de,dd,c9,i=dd,c9,i,dn(dl(dn(i,c9),dd),dl(i,c9))+dn(dt(i,28),ds(i,25),ds(i,30))+cC;cC=dn(dt(e,14),dt(e,18),ds(e,23))+dn(df,dl(e,dn(d,df)))+dg+db[U+4]+da[U+3]dg,df,d,e=df,d,e,cC+de;de,dd,c9,i=dd,c9,i,dn(dl(dn(i,c9),dd),dl(i,c9))+dn(dt(i,28),ds(i,25),ds(i,30))+cC;cC=dn(dt(e,14),dt(e,18),ds(e,23))+dn(df,dl(e,dn(d,df)))+dg+db[U+5]+da[U+4]dg,df,d,e=df,d,e,cC+de;de,dd,c9,i=dd,c9,i,dn(dl(dn(i,c9),dd),dl(i,c9))+dn(dt(i,28),ds(i,25),ds(i,30))+cC;cC=dn(dt(e,14),dt(e,18),ds(e,23))+dn(df,dl(e,dn(d,df)))+dg+db[U+6]+da[U+5]dg,df,d,e=df,d,e,cC+de;de,dd,c9,i=dd,c9,i,dn(dl(dn(i,c9),dd),dl(i,c9))+dn(dt(i,28),ds(i,25),ds(i,30))+cC;cC=dn(dt(e,14),dt(e,18),ds(e,23))+dn(df,dl(e,dn(d,df)))+dg+db[U+7]+da[U+6]dg,df,d,e=df,d,e,cC+de;de,dd,c9,i=dd,c9,i,dn(dl(dn(i,c9),dd),dl(i,c9))+dn(dt(i,28),ds(i,25),ds(i,30))+cC;cC=dn(dt(e,14),dt(e,18),ds(e,23))+dn(df,dl(e,dn(d,df)))+dg+db[U+8]+da[U+7]dg,df,d,e=df,d,e,cC+de;de,dd,c9,i=dd,c9,i,dn(dl(dn(i,c9),dd),dl(i,c9))+dn(dt(i,28),ds(i,25),ds(i,30))+cC end;d7[1]=i+d7[1]d7[2]=c9+d7[2]d7[3]=dd+d7[3]d7[4]=de+d7[4]d7[5]=e+d7[5]d7[6]=d+d7[6]d7[7]=df+d7[7]d7[8]=dg+d7[8]end end else local dD=c8.typeof"union{int64_t i64; struct{int32_t lo, hi;} i32;}"do local b3=dD(1)if b3.i32.lo<b3.i32.hi then dD=c8.typeof"union{int64_t i64; struct{int32_t hi, lo;} i32;}"end end;local dE=c8.typeof("$[?]",dD)local dF=dE(3)local function dG(i)dF[0].i64=i;local dH,dI=dF[0].i32.lo,dF[0].i32.hi;local dJ=ci(ch(ck(dH,1),cj(dI,31)),ch(ck(dH,8),cj(dI,24)),ch(ck(dH,7),cj(dI,25)))local dK=ci(ch(ck(dI,1),cj(dH,31)),ch(ck(dI,8),cj(dH,24)),ck(dI,7))return dK*di(2^32)+dk(dj(dJ))end;local function dL(c9)dF[0].i64=c9;local dM,dN=dF[0].i32.lo,dF[0].i32.hi;local dO=ci(ch(ck(dM,19),cj(dN,13)),ch(cj(dM,3),ck(dN,29)),ch(ck(dM,6),cj(dN,26)))local dP=ci(ch(ck(dN,19),cj(dM,13)),ch(cj(dN,3),ck(dM,29)),ck(dN,6))return dP*di(2^32)+dk(dj(dO))end;local function dQ(e)dF[0].i64=e;local dR,dS=dF[0].i32.lo,dF[0].i32.hi;local dO=ci(ch(ck(dR,14),cj(dS,18)),ch(ck(dR,18),cj(dS,14)),ch(cj(dR,23),ck(dS,9)))local dP=ci(ch(ck(dS,14),cj(dR,18)),ch(ck(dS,18),cj(dR,14)),ch(cj(dS,23),ck(dR,9)))return dP*di(2^32)+dk(dj(dO))end;local function dT(i)dF[0].i64=i;local dM,dN=dF[0].i32.lo,dF[0].i32.hi;local dO=ci(ch(ck(dM,28),cj(dN,4)),ch(cj(dM,30),ck(dN,2)),ch(cj(dM,25),ck(dN,7)))local dP=ci(ch(ck(dN,28),cj(dM,4)),ch(cj(dN,30),ck(dM,2)),ch(cj(dN,25),ck(dM,7)))return dP*di(2^32)+dk(dj(dO))end;local function dU(e,d,df)dF[0].i64=d;dF[1].i64=df;dF[2].i64=e;local dV,dW=dF[0].i32.lo,dF[0].i32.hi;local dX,dY=dF[1].i32.lo,dF[1].i32.hi;local dR,dS=dF[2].i32.lo,dF[2].i32.hi;local dZ=ci(dX,cg(dR,ci(dV,dX)))local d_=ci(dY,cg(dS,ci(dW,dY)))return d_*di(2^32)+dk(dj(dZ))end;local function e0(i,c9,dd)dF[0].i64=i;dF[1].i64=c9;dF[2].i64=dd;local dH,dI=dF[0].i32.lo,dF[0].i32.hi;local dM,dN=dF[1].i32.lo,dF[1].i32.hi;local e1,e2=dF[2].i32.lo,dF[2].i32.hi;local dZ=ci(cg(ci(dH,dM),e1),cg(dH,dM))local d_=ci(cg(ci(dI,dN),e2),cg(dI,dN))return d_*di(2^32)+dk(dj(dZ))end;function cX(dC)dF[0].i64=dC;local e3,e4=dF[0].i32.lo,dF[0].i32.hi;e3=ci(e3,0xA5A5A5A5)e4=ci(e4,0xA5A5A5A5)return e4*di(2^32)+dk(dj(e3))end;function cW(dC)dF[0].i64=dC;return cp(dF[0].i32.hi)..cp(dF[0].i32.lo)end;function cG(d7,cc,d8,d9,d5)local da,db=dh,cK;for dc=d9,d9+d5-1,128 do for U=0,15 do dc=dc+8;local i,c9,dd,de,e,d,df,dg=I(d8,dc-7,dc)da[U]=ch(cj(i,24),cj(c9,16),cj(dd,8),de)*di(2^32)+dk(dj(ch(cj(e,24),cj(d,16),cj(df,8),dg)))end;for U=16,79 do da[U]=dG(da[U-15])+dL(da[U-2])+da[U-7]+da[U-16]end;local i,c9,dd,de,e,d,df,dg=d7[1],d7[2],d7[3],d7[4],d7[5],d7[6],d7[7],d7[8]for U=0,79,8 do local cC=dQ(e)+dU(e,d,df)+dg+db[U+1]+da[U]dg,df,d,e=df,d,e,cC+de;de,dd,c9,i=dd,c9,i,e0(i,c9,dd)+dT(i)+cC;cC=dQ(e)+dU(e,d,df)+dg+db[U+2]+da[U+1]dg,df,d,e=df,d,e,cC+de;de,dd,c9,i=dd,c9,i,e0(i,c9,dd)+dT(i)+cC;cC=dQ(e)+dU(e,d,df)+dg+db[U+3]+da[U+2]dg,df,d,e=df,d,e,cC+de;de,dd,c9,i=dd,c9,i,e0(i,c9,dd)+dT(i)+cC;cC=dQ(e)+dU(e,d,df)+dg+db[U+4]+da[U+3]dg,df,d,e=df,d,e,cC+de;de,dd,c9,i=dd,c9,i,e0(i,c9,dd)+dT(i)+cC;cC=dQ(e)+dU(e,d,df)+dg+db[U+5]+da[U+4]dg,df,d,e=df,d,e,cC+de;de,dd,c9,i=dd,c9,i,e0(i,c9,dd)+dT(i)+cC;cC=dQ(e)+dU(e,d,df)+dg+db[U+6]+da[U+5]dg,df,d,e=df,d,e,cC+de;de,dd,c9,i=dd,c9,i,e0(i,c9,dd)+dT(i)+cC;cC=dQ(e)+dU(e,d,df)+dg+db[U+7]+da[U+6]dg,df,d,e=df,d,e,cC+de;de,dd,c9,i=dd,c9,i,e0(i,c9,dd)+dT(i)+cC;cC=dQ(e)+dU(e,d,df)+dg+db[U+8]+da[U+7]dg,df,d,e=df,d,e,cC+de;de,dd,c9,i=dd,c9,i,e0(i,c9,dd)+dT(i)+cC end;d7[1]=i+d7[1]d7[2]=c9+d7[2]d7[3]=dd+d7[3]d7[4]=de+d7[4]d7[5]=e+d7[5]d7[6]=d+d7[6]d7[7]=df+d7[7]d7[8]=dg+d7[8]end end end;function cH(d7,d8,d9,d5)local da,db=d6,cT;for dc=d9,d9+d5-1,64 do for U=0,15 do dc=dc+4;local i,c9,dd,de=I(d8,dc-3,dc)da[U]=ch(cj(de,24),cj(dd,16),cj(c9,8),i)end;local i,c9,dd,de=d7[1],d7[2],d7[3],d7[4]for U=0,15,4 do i,de,dd,c9=de,dd,c9,co(cl(ci(de,cg(c9,ci(dd,de)))+db[U+1]+da[U]+i,7)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(de,cg(c9,ci(dd,de)))+db[U+2]+da[U+1]+i,12)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(de,cg(c9,ci(dd,de)))+db[U+3]+da[U+2]+i,17)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(de,cg(c9,ci(dd,de)))+db[U+4]+da[U+3]+i,22)+c9)end;for U=16,31,4 do local df=5*U;i,de,dd,c9=de,dd,c9,co(cl(ci(dd,cg(de,ci(c9,dd)))+db[U+1]+da[cg(df+1,15)]+i,5)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(dd,cg(de,ci(c9,dd)))+db[U+2]+da[cg(df+6,15)]+i,9)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(dd,cg(de,ci(c9,dd)))+db[U+3]+da[cg(df-5,15)]+i,14)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(dd,cg(de,ci(c9,dd)))+db[U+4]+da[cg(df,15)]+i,20)+c9)end;for U=32,47,4 do local df=3*U;i,de,dd,c9=de,dd,c9,co(cl(ci(c9,dd,de)+db[U+1]+da[cg(df+5,15)]+i,4)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(c9,dd,de)+db[U+2]+da[cg(df+8,15)]+i,11)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(c9,dd,de)+db[U+3]+da[cg(df-5,15)]+i,16)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(c9,dd,de)+db[U+4]+da[cg(df-2,15)]+i,23)+c9)end;for U=48,63,4 do local df=7*U;i,de,dd,c9=de,dd,c9,co(cl(ci(dd,ch(c9,cn(de)))+db[U+1]+da[cg(df,15)]+i,6)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(dd,ch(c9,cn(de)))+db[U+2]+da[cg(df+7,15)]+i,10)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(dd,ch(c9,cn(de)))+db[U+3]+da[cg(df-2,15)]+i,15)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(dd,ch(c9,cn(de)))+db[U+4]+da[cg(df+5,15)]+i,21)+c9)end;d7[1],d7[2],d7[3],d7[4]=co(i+d7[1]),co(c9+d7[2]),co(dd+d7[3]),co(de+d7[4])end end;function cI(d7,d8,d9,d5)local da=d6;for dc=d9,d9+d5-1,64 do for U=0,15 do dc=dc+4;local i,c9,dd,de=I(d8,dc-3,dc)da[U]=ch(cj(i,24),cj(c9,16),cj(dd,8),de)end;for U=16,79 do da[U]=cl(ci(da[U-3],da[U-8],da[U-14],da[U-16]),1)end;local i,c9,dd,de,e=d7[1],d7[2],d7[3],d7[4],d7[5]for U=0,19,5 do e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(de,cg(c9,ci(de,dd)))+da[U]+0x5A827999+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(de,cg(c9,ci(de,dd)))+da[U+1]+0x5A827999+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(de,cg(c9,ci(de,dd)))+da[U+2]+0x5A827999+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(de,cg(c9,ci(de,dd)))+da[U+3]+0x5A827999+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(de,cg(c9,ci(de,dd)))+da[U+4]+0x5A827999+e)end;for U=20,39,5 do e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U]+0x6ED9EBA1+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U+1]+0x6ED9EBA1+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U+2]+0x6ED9EBA1+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U+3]+0x6ED9EBA1+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U+4]+0x6ED9EBA1+e)end;for U=40,59,5 do e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(cg(de,ci(c9,dd)),cg(c9,dd))+da[U]+0x8F1BBCDC+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(cg(de,ci(c9,dd)),cg(c9,dd))+da[U+1]+0x8F1BBCDC+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(cg(de,ci(c9,dd)),cg(c9,dd))+da[U+2]+0x8F1BBCDC+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(cg(de,ci(c9,dd)),cg(c9,dd))+da[U+3]+0x8F1BBCDC+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(cg(de,ci(c9,dd)),cg(c9,dd))+da[U+4]+0x8F1BBCDC+e)end;for U=60,79,5 do e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U]+0xCA62C1D6+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U+1]+0xCA62C1D6+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U+2]+0xCA62C1D6+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U+3]+0xCA62C1D6+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U+4]+0xCA62C1D6+e)end;d7[1],d7[2],d7[3],d7[4],d7[5]=co(i+d7[1]),co(c9+d7[2]),co(dd+d7[3]),co(de+d7[4]),co(e+d7[5])end end end;if cf=="FFI"and not c6 or cf=="LJ"then if cf=="FFI"then local e5=c8.typeof"int32_t[31]"function cE()return e5()end end;function cJ(e6,e7,d8,d9,d5,dw)local e8,e9=cO,cP;local dy=ck(dw,3)for dc=d9,d9+d5-1,dw do for U=1,dy do local i,c9,dd,de=I(d8,dc+1,dc+4)e6[U]=ci(e6[U],ch(cj(de,24),cj(dd,16),cj(c9,8),i))dc=dc+8;i,c9,dd,de=I(d8,dc-3,dc)e7[U]=ci(e7[U],ch(cj(de,24),cj(dd,16),cj(c9,8),i))end;for dz=1,24 do for U=1,5 do e6[25+U]=ci(e6[U],e6[U+5],e6[U+10],e6[U+15],e6[U+20])end;for U=1,5 do e7[25+U]=ci(e7[U],e7[U+5],e7[U+10],e7[U+15],e7[U+20])end;local ea=ci(e6[26],cj(e6[28],1),ck(e7[28],31))local eb=ci(e7[26],cj(e7[28],1),ck(e6[28],31))e6[2],e7[2],e6[7],e7[7],e6[12],e7[12],e6[17],e7[17]=ci(ck(ci(ea,e6[7]),20),cj(ci(eb,e7[7]),12)),ci(ck(ci(eb,e7[7]),20),cj(ci(ea,e6[7]),12)),ci(ck(ci(ea,e6[17]),19),cj(ci(eb,e7[17]),13)),ci(ck(ci(eb,e7[17]),19),cj(ci(ea,e6[17]),13)),ci(cj(ci(ea,e6[2]),1),ck(ci(eb,e7[2]),31)),ci(cj(ci(eb,e7[2]),1),ck(ci(ea,e6[2]),31)),ci(cj(ci(ea,e6[12]),10),ck(ci(eb,e7[12]),22)),ci(cj(ci(eb,e7[12]),10),ck(ci(ea,e6[12]),22))local ec,d7=ci(ea,e6[22]),ci(eb,e7[22])e6[22],e7[22]=ci(cj(ec,2),ck(d7,30)),ci(cj(d7,2),ck(ec,30))ea=ci(e6[27],cj(e6[29],1),ck(e7[29],31))eb=ci(e7[27],cj(e7[29],1),ck(e6[29],31))e6[3],e7[3],e6[8],e7[8],e6[13],e7[13],e6[23],e7[23]=ci(ck(ci(ea,e6[13]),21),cj(ci(eb,e7[13]),11)),ci(ck(ci(eb,e7[13]),21),cj(ci(ea,e6[13]),11)),ci(ck(ci(ea,e6[23]),3),cj(ci(eb,e7[23]),29)),ci(ck(ci(eb,e7[23]),3),cj(ci(ea,e6[23]),29)),ci(cj(ci(ea,e6[8]),6),ck(ci(eb,e7[8]),26)),ci(cj(ci(eb,e7[8]),6),ck(ci(ea,e6[8]),26)),ci(ck(ci(ea,e6[3]),2),cj(ci(eb,e7[3]),30)),ci(ck(ci(eb,e7[3]),2),cj(ci(ea,e6[3]),30))ec,d7=ci(ea,e6[18]),ci(eb,e7[18])e6[18],e7[18]=ci(cj(ec,15),ck(d7,17)),ci(cj(d7,15),ck(ec,17))ea=ci(e6[28],cj(e6[30],1),ck(e7[30],31))eb=ci(e7[28],cj(e7[30],1),ck(e6[30],31))e6[4],e7[4],e6[9],e7[9],e6[19],e7[19],e6[24],e7[24]=ci(cj(ci(ea,e6[19]),21),ck(ci(eb,e7[19]),11)),ci(cj(ci(eb,e7[19]),21),ck(ci(ea,e6[19]),11)),ci(cj(ci(ea,e6[4]),28),ck(ci(eb,e7[4]),4)),ci(cj(ci(eb,e7[4]),28),ck(ci(ea,e6[4]),4)),ci(ck(ci(ea,e6[24]),8),cj(ci(eb,e7[24]),24)),ci(ck(ci(eb,e7[24]),8),cj(ci(ea,e6[24]),24)),ci(ck(ci(ea,e6[9]),9),cj(ci(eb,e7[9]),23)),ci(ck(ci(eb,e7[9]),9),cj(ci(ea,e6[9]),23))ec,d7=ci(ea,e6[14]),ci(eb,e7[14])e6[14],e7[14]=ci(cj(ec,25),ck(d7,7)),ci(cj(d7,25),ck(ec,7))ea=ci(e6[29],cj(e6[26],1),ck(e7[26],31))eb=ci(e7[29],cj(e7[26],1),ck(e6[26],31))e6[5],e7[5],e6[15],e7[15],e6[20],e7[20],e6[25],e7[25]=ci(cj(ci(ea,e6[25]),14),ck(ci(eb,e7[25]),18)),ci(cj(ci(eb,e7[25]),14),ck(ci(ea,e6[25]),18)),ci(cj(ci(ea,e6[20]),8),ck(ci(eb,e7[20]),24)),ci(cj(ci(eb,e7[20]),8),ck(ci(ea,e6[20]),24)),ci(cj(ci(ea,e6[5]),27),ck(ci(eb,e7[5]),5)),ci(cj(ci(eb,e7[5]),27),ck(ci(ea,e6[5]),5)),ci(ck(ci(ea,e6[15]),25),cj(ci(eb,e7[15]),7)),ci(ck(ci(eb,e7[15]),25),cj(ci(ea,e6[15]),7))ec,d7=ci(ea,e6[10]),ci(eb,e7[10])e6[10],e7[10]=ci(cj(ec,20),ck(d7,12)),ci(cj(d7,20),ck(ec,12))ea=ci(e6[30],cj(e6[27],1),ck(e7[27],31))eb=ci(e7[30],cj(e7[27],1),ck(e6[27],31))e6[6],e7[6],e6[11],e7[11],e6[16],e7[16],e6[21],e7[21]=ci(cj(ci(ea,e6[11]),3),ck(ci(eb,e7[11]),29)),ci(cj(ci(eb,e7[11]),3),ck(ci(ea,e6[11]),29)),ci(cj(ci(ea,e6[21]),18),ck(ci(eb,e7[21]),14)),ci(cj(ci(eb,e7[21]),18),ck(ci(ea,e6[21]),14)),ci(ck(ci(ea,e6[6]),28),cj(ci(eb,e7[6]),4)),ci(ck(ci(eb,e7[6]),28),cj(ci(ea,e6[6]),4)),ci(ck(ci(ea,e6[16]),23),cj(ci(eb,e7[16]),9)),ci(ck(ci(eb,e7[16]),23),cj(ci(ea,e6[16]),9))e6[1],e7[1]=ci(ea,e6[1]),ci(eb,e7[1])e6[1],e6[2],e6[3],e6[4],e6[5]=ci(e6[1],cg(cn(e6[2]),e6[3]),e8[dz]),ci(e6[2],cg(cn(e6[3]),e6[4])),ci(e6[3],cg(cn(e6[4]),e6[5])),ci(e6[4],cg(cn(e6[5]),e6[1])),ci(e6[5],cg(cn(e6[1]),e6[2]))e6[6],e6[7],e6[8],e6[9],e6[10]=ci(e6[9],cg(cn(e6[10]),e6[6])),ci(e6[10],cg(cn(e6[6]),e6[7])),ci(e6[6],cg(cn(e6[7]),e6[8])),ci(e6[7],cg(cn(e6[8]),e6[9])),ci(e6[8],cg(cn(e6[9]),e6[10]))e6[11],e6[12],e6[13],e6[14],e6[15]=ci(e6[12],cg(cn(e6[13]),e6[14])),ci(e6[13],cg(cn(e6[14]),e6[15])),ci(e6[14],cg(cn(e6[15]),e6[11])),ci(e6[15],cg(cn(e6[11]),e6[12])),ci(e6[11],cg(cn(e6[12]),e6[13]))e6[16],e6[17],e6[18],e6[19],e6[20]=ci(e6[20],cg(cn(e6[16]),e6[17])),ci(e6[16],cg(cn(e6[17]),e6[18])),ci(e6[17],cg(cn(e6[18]),e6[19])),ci(e6[18],cg(cn(e6[19]),e6[20])),ci(e6[19],cg(cn(e6[20]),e6[16]))e6[21],e6[22],e6[23],e6[24],e6[25]=ci(e6[23],cg(cn(e6[24]),e6[25])),ci(e6[24],cg(cn(e6[25]),e6[21])),ci(e6[25],cg(cn(e6[21]),e6[22])),ci(e6[21],cg(cn(e6[22]),e6[23])),ci(e6[22],cg(cn(e6[23]),e6[24]))e7[1],e7[2],e7[3],e7[4],e7[5]=ci(e7[1],cg(cn(e7[2]),e7[3]),e9[dz]),ci(e7[2],cg(cn(e7[3]),e7[4])),ci(e7[3],cg(cn(e7[4]),e7[5])),ci(e7[4],cg(cn(e7[5]),e7[1])),ci(e7[5],cg(cn(e7[1]),e7[2]))e7[6],e7[7],e7[8],e7[9],e7[10]=ci(e7[9],cg(cn(e7[10]),e7[6])),ci(e7[10],cg(cn(e7[6]),e7[7])),ci(e7[6],cg(cn(e7[7]),e7[8])),ci(e7[7],cg(cn(e7[8]),e7[9])),ci(e7[8],cg(cn(e7[9]),e7[10]))e7[11],e7[12],e7[13],e7[14],e7[15]=ci(e7[12],cg(cn(e7[13]),e7[14])),ci(e7[13],cg(cn(e7[14]),e7[15])),ci(e7[14],cg(cn(e7[15]),e7[11])),ci(e7[15],cg(cn(e7[11]),e7[12])),ci(e7[11],cg(cn(e7[12]),e7[13]))e7[16],e7[17],e7[18],e7[19],e7[20]=ci(e7[20],cg(cn(e7[16]),e7[17])),ci(e7[16],cg(cn(e7[17]),e7[18])),ci(e7[17],cg(cn(e7[18]),e7[19])),ci(e7[18],cg(cn(e7[19]),e7[20])),ci(e7[19],cg(cn(e7[20]),e7[16]))e7[21],e7[22],e7[23],e7[24],e7[25]=ci(e7[23],cg(cn(e7[24]),e7[25])),ci(e7[24],cg(cn(e7[25]),e7[21])),ci(e7[25],cg(cn(e7[21]),e7[22])),ci(e7[21],cg(cn(e7[22]),e7[23])),ci(e7[22],cg(cn(e7[23]),e7[24]))end end end end;if cf=="LJ"then function cF(d7,d8,d9,d5)local da,db=cZ,cL;for dc=d9,d9+d5-1,64 do for U=1,16 do dc=dc+4;local i,c9,dd,de=I(d8,dc-3,dc)da[U]=ch(cj(i,24),cj(c9,16),cj(dd,8),de)end;for U=17,64 do local i,c9=da[U-15],da[U-2]da[U]=co(co(ci(cm(i,7),cl(i,14),ck(i,3))+ci(cl(c9,15),cl(c9,13),ck(c9,10)))+co(da[U-7]+da[U-16]))end;local i,c9,dd,de,e,d,df,dg=d7[1],d7[2],d7[3],d7[4],d7[5],d7[6],d7[7],d7[8]for U=1,64,8 do local cC=co(ci(cm(e,6),cm(e,11),cl(e,7))+ci(df,cg(e,ci(d,df)))+db[U]+da[U]+dg)dg,df,d,e=df,d,e,co(de+cC)de,dd,c9,i=dd,c9,i,co(ci(cg(i,ci(c9,dd)),cg(c9,dd))+ci(cm(i,2),cm(i,13),cl(i,10))+cC)cC=co(ci(cm(e,6),cm(e,11),cl(e,7))+ci(df,cg(e,ci(d,df)))+db[U+1]+da[U+1]+dg)dg,df,d,e=df,d,e,co(de+cC)de,dd,c9,i=dd,c9,i,co(ci(cg(i,ci(c9,dd)),cg(c9,dd))+ci(cm(i,2),cm(i,13),cl(i,10))+cC)cC=co(ci(cm(e,6),cm(e,11),cl(e,7))+ci(df,cg(e,ci(d,df)))+db[U+2]+da[U+2]+dg)dg,df,d,e=df,d,e,co(de+cC)de,dd,c9,i=dd,c9,i,co(ci(cg(i,ci(c9,dd)),cg(c9,dd))+ci(cm(i,2),cm(i,13),cl(i,10))+cC)cC=co(ci(cm(e,6),cm(e,11),cl(e,7))+ci(df,cg(e,ci(d,df)))+db[U+3]+da[U+3]+dg)dg,df,d,e=df,d,e,co(de+cC)de,dd,c9,i=dd,c9,i,co(ci(cg(i,ci(c9,dd)),cg(c9,dd))+ci(cm(i,2),cm(i,13),cl(i,10))+cC)cC=co(ci(cm(e,6),cm(e,11),cl(e,7))+ci(df,cg(e,ci(d,df)))+db[U+4]+da[U+4]+dg)dg,df,d,e=df,d,e,co(de+cC)de,dd,c9,i=dd,c9,i,co(ci(cg(i,ci(c9,dd)),cg(c9,dd))+ci(cm(i,2),cm(i,13),cl(i,10))+cC)cC=co(ci(cm(e,6),cm(e,11),cl(e,7))+ci(df,cg(e,ci(d,df)))+db[U+5]+da[U+5]+dg)dg,df,d,e=df,d,e,co(de+cC)de,dd,c9,i=dd,c9,i,co(ci(cg(i,ci(c9,dd)),cg(c9,dd))+ci(cm(i,2),cm(i,13),cl(i,10))+cC)cC=co(ci(cm(e,6),cm(e,11),cl(e,7))+ci(df,cg(e,ci(d,df)))+db[U+6]+da[U+6]+dg)dg,df,d,e=df,d,e,co(de+cC)de,dd,c9,i=dd,c9,i,co(ci(cg(i,ci(c9,dd)),cg(c9,dd))+ci(cm(i,2),cm(i,13),cl(i,10))+cC)cC=co(ci(cm(e,6),cm(e,11),cl(e,7))+ci(df,cg(e,ci(d,df)))+db[U+7]+da[U+7]+dg)dg,df,d,e=df,d,e,co(de+cC)de,dd,c9,i=dd,c9,i,co(ci(cg(i,ci(c9,dd)),cg(c9,dd))+ci(cm(i,2),cm(i,13),cl(i,10))+cC)end;d7[1],d7[2],d7[3],d7[4]=co(i+d7[1]),co(c9+d7[2]),co(dd+d7[3]),co(de+d7[4])d7[5],d7[6],d7[7],d7[8]=co(e+d7[5]),co(d+d7[6]),co(df+d7[7]),co(dg+d7[8])end end;local function ed(dH,dI,dM,dN,e1,e2,ee,ef)local eg=dH%2^32+dM%2^32+e1%2^32+ee%2^32;local eh=dI+dN+e2+ef;local dZ=co(eg)local d_=co(eh+f(eg/2^32))return dZ,d_ end;if c7=="x86"then function cG(ei,ej,d8,d9,d5)local da,ek,el=cZ,cK,cL;for dc=d9,d9+d5-1,128 do for U=1,16*2 do dc=dc+4;local i,c9,dd,de=I(d8,dc-3,dc)da[U]=ch(cj(i,24),cj(c9,16),cj(dd,8),de)end;for em=17*2,80*2,2 do local dH,dI=da[em-30],da[em-31]local dJ=ci(ch(ck(dH,1),cj(dI,31)),ch(ck(dH,8),cj(dI,24)),ch(ck(dH,7),cj(dI,25)))local dK=ci(ch(ck(dI,1),cj(dH,31)),ch(ck(dI,8),cj(dH,24)),ck(dI,7))local dM,dN=da[em-4],da[em-5]local dO=ci(ch(ck(dM,19),cj(dN,13)),ch(cj(dM,3),ck(dN,29)),ch(ck(dM,6),cj(dN,26)))local dP=ci(ch(ck(dN,19),cj(dM,13)),ch(cj(dN,3),ck(dM,29)),ck(dN,6))da[em],da[em-1]=ed(dJ,dK,dO,dP,da[em-14],da[em-15],da[em-32],da[em-33])end;local dH,dM,e1,ee,dR,dV,dX,en=ei[1],ei[2],ei[3],ei[4],ei[5],ei[6],ei[7],ei[8]local dI,dN,e2,ef,dS,dW,dY,eo=ej[1],ej[2],ej[3],ej[4],ej[5],ej[6],ej[7],ej[8]local ep=0;for U=1,80 do local dJ=ci(dX,cg(dR,ci(dV,dX)))local dK=ci(dY,cg(dS,ci(dW,dY)))local dO=ci(ch(ck(dR,14),cj(dS,18)),ch(ck(dR,18),cj(dS,14)),ch(cj(dR,23),ck(dS,9)))local dP=ci(ch(ck(dS,14),cj(dR,18)),ch(ck(dS,18),cj(dR,14)),ch(cj(dS,23),ck(dR,9)))local eg=dO%2^32+dJ%2^32+en%2^32+ek[U]+da[2*U]%2^32;local eq,er=co(eg),co(dP+dK+eo+el[U]+da[2*U-1]+f(eg/2^32))ep=ep+ep;en,eo,dX,dY,dV,dW=ch(ep,dX),ch(ep,dY),ch(ep,dV),ch(ep,dW),ch(ep,dR),ch(ep,dS)local eg=eq%2^32+ee%2^32;dR,dS=co(eg),co(er+ef+f(eg/2^32))ee,ef,e1,e2,dM,dN=ch(ep,e1),ch(ep,e2),ch(ep,dM),ch(ep,dN),ch(ep,dH),ch(ep,dI)dO=ci(ch(ck(dM,28),cj(dN,4)),ch(cj(dM,30),ck(dN,2)),ch(cj(dM,25),ck(dN,7)))dP=ci(ch(ck(dN,28),cj(dM,4)),ch(cj(dN,30),ck(dM,2)),ch(cj(dN,25),ck(dM,7)))dJ=ch(cg(ee,e1),cg(dM,ci(ee,e1)))dK=ch(cg(ef,e2),cg(dN,ci(ef,e2)))local eg=eq%2^32+dJ%2^32+dO%2^32;dH,dI=co(eg),co(er+dK+dP+f(eg/2^32))end;ei[1],ej[1]=ed(ei[1],ej[1],dH,dI,0,0,0,0)ei[2],ej[2]=ed(ei[2],ej[2],dM,dN,0,0,0,0)ei[3],ej[3]=ed(ei[3],ej[3],e1,e2,0,0,0,0)ei[4],ej[4]=ed(ei[4],ej[4],ee,ef,0,0,0,0)ei[5],ej[5]=ed(ei[5],ej[5],dR,dS,0,0,0,0)ei[6],ej[6]=ed(ei[6],ej[6],dV,dW,0,0,0,0)ei[7],ej[7]=ed(ei[7],ej[7],dX,dY,0,0,0,0)ei[8],ej[8]=ed(ei[8],ej[8],en,eo,0,0,0,0)end end else function cG(ei,ej,d8,d9,d5)local da,ek,el=cZ,cK,cL;for dc=d9,d9+d5-1,128 do for U=1,16*2 do dc=dc+4;local i,c9,dd,de=I(d8,dc-3,dc)da[U]=ch(cj(i,24),cj(c9,16),cj(dd,8),de)end;for em=17*2,80*2,2 do local dH,dI=da[em-30],da[em-31]local dJ=ci(ch(ck(dH,1),cj(dI,31)),ch(ck(dH,8),cj(dI,24)),ch(ck(dH,7),cj(dI,25)))local dK=ci(ch(ck(dI,1),cj(dH,31)),ch(ck(dI,8),cj(dH,24)),ck(dI,7))local dM,dN=da[em-4],da[em-5]local dO=ci(ch(ck(dM,19),cj(dN,13)),ch(cj(dM,3),ck(dN,29)),ch(ck(dM,6),cj(dN,26)))local dP=ci(ch(ck(dN,19),cj(dM,13)),ch(cj(dN,3),ck(dM,29)),ck(dN,6))da[em],da[em-1]=ed(dJ,dK,dO,dP,da[em-14],da[em-15],da[em-32],da[em-33])end;local dH,dM,e1,ee,dR,dV,dX,en=ei[1],ei[2],ei[3],ei[4],ei[5],ei[6],ei[7],ei[8]local dI,dN,e2,ef,dS,dW,dY,eo=ej[1],ej[2],ej[3],ej[4],ej[5],ej[6],ej[7],ej[8]for U=1,80 do local dJ=ci(dX,cg(dR,ci(dV,dX)))local dK=ci(dY,cg(dS,ci(dW,dY)))local dO=ci(ch(ck(dR,14),cj(dS,18)),ch(ck(dR,18),cj(dS,14)),ch(cj(dR,23),ck(dS,9)))local dP=ci(ch(ck(dS,14),cj(dR,18)),ch(ck(dS,18),cj(dR,14)),ch(cj(dS,23),ck(dR,9)))local eg=dO%2^32+dJ%2^32+en%2^32+ek[U]+da[2*U]%2^32;local eq,er=co(eg),co(dP+dK+eo+el[U]+da[2*U-1]+f(eg/2^32))en,eo,dX,dY,dV,dW=dX,dY,dV,dW,dR,dS;local eg=eq%2^32+ee%2^32;dR,dS=co(eg),co(er+ef+f(eg/2^32))ee,ef,e1,e2,dM,dN=e1,e2,dM,dN,dH,dI;dO=ci(ch(ck(dM,28),cj(dN,4)),ch(cj(dM,30),ck(dN,2)),ch(cj(dM,25),ck(dN,7)))dP=ci(ch(ck(dN,28),cj(dM,4)),ch(cj(dN,30),ck(dM,2)),ch(cj(dN,25),ck(dM,7)))dJ=ch(cg(ee,e1),cg(dM,ci(ee,e1)))dK=ch(cg(ef,e2),cg(dN,ci(ef,e2)))local eg=eq%2^32+dO%2^32+dJ%2^32;dH,dI=co(eg),co(er+dP+dK+f(eg/2^32))end;ei[1],ej[1]=ed(ei[1],ej[1],dH,dI,0,0,0,0)ei[2],ej[2]=ed(ei[2],ej[2],dM,dN,0,0,0,0)ei[3],ej[3]=ed(ei[3],ej[3],e1,e2,0,0,0,0)ei[4],ej[4]=ed(ei[4],ej[4],ee,ef,0,0,0,0)ei[5],ej[5]=ed(ei[5],ej[5],dR,dS,0,0,0,0)ei[6],ej[6]=ed(ei[6],ej[6],dV,dW,0,0,0,0)ei[7],ej[7]=ed(ei[7],ej[7],dX,dY,0,0,0,0)ei[8],ej[8]=ed(ei[8],ej[8],en,eo,0,0,0,0)end end end;function cH(d7,d8,d9,d5)local da,db=cZ,cT;for dc=d9,d9+d5-1,64 do for U=1,16 do dc=dc+4;local i,c9,dd,de=I(d8,dc-3,dc)da[U]=ch(cj(de,24),cj(dd,16),cj(c9,8),i)end;local i,c9,dd,de=d7[1],d7[2],d7[3],d7[4]for U=1,16,4 do i,de,dd,c9=de,dd,c9,co(cl(ci(de,cg(c9,ci(dd,de)))+db[U]+da[U]+i,7)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(de,cg(c9,ci(dd,de)))+db[U+1]+da[U+1]+i,12)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(de,cg(c9,ci(dd,de)))+db[U+2]+da[U+2]+i,17)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(de,cg(c9,ci(dd,de)))+db[U+3]+da[U+3]+i,22)+c9)end;for U=17,32,4 do local df=5*U-4;i,de,dd,c9=de,dd,c9,co(cl(ci(dd,cg(de,ci(c9,dd)))+db[U]+da[cg(df,15)+1]+i,5)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(dd,cg(de,ci(c9,dd)))+db[U+1]+da[cg(df+5,15)+1]+i,9)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(dd,cg(de,ci(c9,dd)))+db[U+2]+da[cg(df+10,15)+1]+i,14)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(dd,cg(de,ci(c9,dd)))+db[U+3]+da[cg(df-1,15)+1]+i,20)+c9)end;for U=33,48,4 do local df=3*U+2;i,de,dd,c9=de,dd,c9,co(cl(ci(c9,dd,de)+db[U]+da[cg(df,15)+1]+i,4)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(c9,dd,de)+db[U+1]+da[cg(df+3,15)+1]+i,11)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(c9,dd,de)+db[U+2]+da[cg(df+6,15)+1]+i,16)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(c9,dd,de)+db[U+3]+da[cg(df-7,15)+1]+i,23)+c9)end;for U=49,64,4 do local df=U*7;i,de,dd,c9=de,dd,c9,co(cl(ci(dd,ch(c9,cn(de)))+db[U]+da[cg(df-7,15)+1]+i,6)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(dd,ch(c9,cn(de)))+db[U+1]+da[cg(df,15)+1]+i,10)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(dd,ch(c9,cn(de)))+db[U+2]+da[cg(df+7,15)+1]+i,15)+c9)i,de,dd,c9=de,dd,c9,co(cl(ci(dd,ch(c9,cn(de)))+db[U+3]+da[cg(df-2,15)+1]+i,21)+c9)end;d7[1],d7[2],d7[3],d7[4]=co(i+d7[1]),co(c9+d7[2]),co(dd+d7[3]),co(de+d7[4])end end;function cI(d7,d8,d9,d5)local da=cZ;for dc=d9,d9+d5-1,64 do for U=1,16 do dc=dc+4;local i,c9,dd,de=I(d8,dc-3,dc)da[U]=ch(cj(i,24),cj(c9,16),cj(dd,8),de)end;for U=17,80 do da[U]=cl(ci(da[U-3],da[U-8],da[U-14],da[U-16]),1)end;local i,c9,dd,de,e=d7[1],d7[2],d7[3],d7[4],d7[5]for U=1,20,5 do e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(de,cg(c9,ci(de,dd)))+da[U]+0x5A827999+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(de,cg(c9,ci(de,dd)))+da[U+1]+0x5A827999+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(de,cg(c9,ci(de,dd)))+da[U+2]+0x5A827999+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(de,cg(c9,ci(de,dd)))+da[U+3]+0x5A827999+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(de,cg(c9,ci(de,dd)))+da[U+4]+0x5A827999+e)end;for U=21,40,5 do e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U]+0x6ED9EBA1+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U+1]+0x6ED9EBA1+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U+2]+0x6ED9EBA1+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U+3]+0x6ED9EBA1+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U+4]+0x6ED9EBA1+e)end;for U=41,60,5 do e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(cg(de,ci(c9,dd)),cg(c9,dd))+da[U]+0x8F1BBCDC+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(cg(de,ci(c9,dd)),cg(c9,dd))+da[U+1]+0x8F1BBCDC+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(cg(de,ci(c9,dd)),cg(c9,dd))+da[U+2]+0x8F1BBCDC+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(cg(de,ci(c9,dd)),cg(c9,dd))+da[U+3]+0x8F1BBCDC+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(cg(de,ci(c9,dd)),cg(c9,dd))+da[U+4]+0x8F1BBCDC+e)end;for U=61,80,5 do e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U]+0xCA62C1D6+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U+1]+0xCA62C1D6+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U+2]+0xCA62C1D6+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U+3]+0xCA62C1D6+e)e,de,dd,c9,i=de,dd,cm(c9,2),i,co(cl(i,5)+ci(c9,dd,de)+da[U+4]+0xCA62C1D6+e)end;d7[1],d7[2],d7[3],d7[4],d7[5]=co(i+d7[1]),co(c9+d7[2]),co(dd+d7[3]),co(de+d7[4]),co(e+d7[5])end end end;if cf=="INT64"then d0=4294967296;d1=4294967296;cY=1;cW,cX,cq,cF,cG,cH,cI,cJ=load[[local a,b,c,d,e,f=...local g,h=string.format,string.unpack;local function i(j)return g("%016x",j)end;local function k(j)return j~0xa5a5a5a5a5a5a5a5 end;local function l(j,m)return j~m end;local n={}local function o(p,q,r,s)local t,u=n,d;local v,w,x,y,z,A,B,C=p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8]for D=r+1,r+s,64 do t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15],t[16]=h(">I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4",q,D)for E=17,64 do local F=t[E-15]F=F<<32|F;local G=t[E-2]G=G<<32|G;t[E]=F>>7~(F>>18)~(F>>35)+G>>17~(G>>19)~(G>>42)+t[E-7]+t[E-16]&1<<32-1 end;local F,G,H,I,J,K,L,M=v,w,x,y,z,A,B,C;for E=1,64 do J=J<<32|(J&1<<32-1)local N=J>>6~(J>>11)~(J>>25)+L~(J&(K~L))+M+u[E]+t[E]M=L;L=K;K=J;J=N+I;I=H;H=G;G=F;F=F<<32|(F&1<<32-1)F=N+F~H&I~(F&H)+F>>2~(F>>13)~(F>>22)end;v=F+v;w=G+w;x=H+x;y=I+y;z=J+z;A=K+A;B=L+B;C=M+C end;p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8]=v,w,x,y,z,A,B,C end;local function O(p,P,q,r,s)local t,u=n,c;local v,w,x,y,z,A,B,C=p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8]for D=r+1,r+s,128 do t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15],t[16]=h(">i8i8i8i8i8i8i8i8i8i8i8i8i8i8i8i8",q,D)for E=17,80 do local F=t[E-15]local G=t[E-2]t[E]=F>>1~(F>>7)~(F>>8)~(F<<56)~(F<<63)+G>>6~(G>>19)~(G>>61)~(G<<3)~(G<<45)+t[E-7]+t[E-16]end;local F,G,H,I,J,K,L,M=v,w,x,y,z,A,B,C;for E=1,80 do local N=J>>14~(J>>18)~(J>>41)~(J<<23)~(J<<46)~(J<<50)+L~(J&(K~L))+M+u[E]+t[E]M=L;L=K;K=J;J=N+I;I=H;H=G;G=F;F=N+F~H&I~(F&H)+F>>28~(F>>34)~(F>>39)~(F<<25)~(F<<30)~(F<<36)end;v=F+v;w=G+w;x=H+x;y=I+y;z=J+z;A=K+A;B=L+B;C=M+C end;p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8]=v,w,x,y,z,A,B,C end;local function Q(p,q,r,s)local t,u,a=n,b,a;local v,w,x,y=p[1],p[2],p[3],p[4]for D=r+1,r+s,64 do t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15],t[16]=h("<I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4",q,D)local F,G,H,I=v,w,x,y;local R=32-7;for E=1,16 do local S=I~(G&(H~I))+F+u[E]+t[E]F=I;I=H;H=G;G=S<<32|(S&1<<32-1)>>R+G;R=a[R]end;R=32-5;for E=17,32 do local S=H~(I&(G~H))+F+u[E]+t[5*E-4&15+1]F=I;I=H;H=G;G=S<<32|(S&1<<32-1)>>R+G;R=a[R]end;R=32-4;for E=33,48 do local S=G~H~I+F+u[E]+t[3*E+2&15+1]F=I;I=H;H=G;G=S<<32|(S&1<<32-1)>>R+G;R=a[R]end;R=32-6;for E=49,64 do local S=H~(G|~I)+F+u[E]+t[E*7-7&15+1]F=I;I=H;H=G;G=S<<32|(S&1<<32-1)>>R+G;R=a[R]end;v=F+v;w=G+w;x=H+x;y=I+y end;p[1],p[2],p[3],p[4]=v,w,x,y end;local function T(p,q,r,s)local t=n;local v,w,x,y,z=p[1],p[2],p[3],p[4],p[5]for D=r+1,r+s,64 do t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15],t[16]=h(">I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4",q,D)for E=17,80 do local F=t[E-3]~t[E-8]~t[E-14]~t[E-16]t[E]=F<<32|F<<1>>32 end;local F,G,H,I,J=v,w,x,y,z;for E=1,20 do local N=F<<32|(F&1<<32-1)>>27+I~(G&(H~I))+0x5A827999+t[E]+J;J=I;I=H;H=G<<32|(G&1<<32-1)>>2;G=F;F=N end;for E=21,40 do local N=F<<32|(F&1<<32-1)>>27+G~H~I+0x6ED9EBA1+t[E]+J;J=I;I=H;H=G<<32|(G&1<<32-1)>>2;G=F;F=N end;for E=41,60 do local N=F<<32|(F&1<<32-1)>>27+G~H&I~(G&H)+0x8F1BBCDC+t[E]+J;J=I;I=H;H=G<<32|(G&1<<32-1)>>2;G=F;F=N end;for E=61,80 do local N=F<<32|(F&1<<32-1)>>27+G~H~I+0xCA62C1D6+t[E]+J;J=I;I=H;H=G<<32|(G&1<<32-1)>>2;G=F;F=N end;v=F+v;w=G+w;x=H+x;y=I+y;z=J+z end;p[1],p[2],p[3],p[4],p[5]=v,w,x,y,z end;local U=e("i8")local function V(W,P,q,r,s,X)local Y=f;local Z=X/8;local _=U[Z]for D=r+1,r+s,X do local a0={h(_,q,D)}for E=1,Z do W[E]=W[E]~a0[E]end;local a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,ab,ac,ad,ae,af,ag,ah,ai,aj,ak,al,am,an,ao,ap=W[1],W[2],W[3],W[4],W[5],W[6],W[7],W[8],W[9],W[10],W[11],W[12],W[13],W[14],W[15],W[16],W[17],W[18],W[19],W[20],W[21],W[22],W[23],W[24],W[25]for aq=1,24 do local ar=a1~a6~ab~ag~al;local as=a2~a7~ac~ah~am;local at=a3~a8~ad~ai~an;local au=a4~a9~ae~aj~ao;local av=a5~aa~af~ak~ap;local aw=ar~(at<<1)~(at>>63)local ax=aw~a2;local ay=aw~a7;local az=aw~ac;local aA=aw~ah;local aB=aw~am;a2=ay<<44~(ay>>20)a7=aA<<45~(aA>>19)ac=ax<<1~(ax>>63)ah=az<<10~(az>>54)am=aB<<2~(aB>>62)aw=as~(au<<1)~(au>>63)ax=aw~a3;ay=aw~a8;az=aw~ad;aA=aw~ai;aB=aw~an;a3=az<<43~(az>>21)a8=aB<<61~(aB>>3)ad=ay<<6~(ay>>58)ai=aA<<15~(aA>>49)an=ax<<62~(ax>>2)aw=at~(av<<1)~(av>>63)ax=aw~a4;ay=aw~a9;az=aw~ae;aA=aw~aj;aB=aw~ao;a4=aA<<21~(aA>>43)a9=ax<<28~(ax>>36)ae=az<<25~(az>>39)aj=aB<<56~(aB>>8)ao=ay<<55~(ay>>9)aw=au~(ar<<1)~(ar>>63)ax=aw~a5;ay=aw~aa;az=aw~af;aA=aw~ak;aB=aw~ap;a5=aB<<14~(aB>>50)aa=ay<<20~(ay>>44)af=aA<<8~(aA>>56)ak=ax<<27~(ax>>37)ap=az<<39~(az>>25)aw=av~(as<<1)~(as>>63)ay=aw~a6;az=aw~ab;aA=aw~ag;aB=aw~al;a6=az<<3~(az>>61)ab=aB<<18~(aB>>46)ag=ay<<36~(ay>>28)al=aA<<41~(aA>>23)a1=aw~a1;a1,a2,a3,a4,a5=a1~(~a2&a3),a2~(~a3&a4),a3~(~a4&a5),a4~(~a5&a1),a5~(~a1&a2)a6,a7,a8,a9,aa=a9~(~aa&a6),aa~(~a6&a7),a6~(~a7&a8),a7~(~a8&a9),a8~(~a9&aa)ab,ac,ad,ae,af=ac~(~ad&ae),ad~(~ae&af),ae~(~af&ab),af~(~ab&ac),ab~(~ac&ad)ag,ah,ai,aj,ak=ak~(~ag&ah),ag~(~ah&ai),ah~(~ai&aj),ai~(~aj&ak),aj~(~ak&ag)al,am,an,ao,ap=an~(~ao&ap),ao~(~ap&al),ap~(~al&am),al~(~am&an),am~(~an&ao)a1=a1~Y[aq]end;W[1]=a1;W[2]=a2;W[3]=a3;W[4]=a4;W[5]=a5;W[6]=a6;W[7]=a7;W[8]=a8;W[9]=a9;W[10]=aa;W[11]=ab;W[12]=ac;W[13]=ad;W[14]=ae;W[15]=af;W[16]=ag;W[17]=ah;W[18]=ai;W[19]=aj;W[20]=ak;W[21]=al;W[22]=am;W[23]=an;W[24]=ao;W[25]=ap end end;return i,k,l,o,O,Q,T,V]](cV,cT,cK,cL,d2,cO)end;if cf=="INT32"then c_=2^32;function cp(aN)return bS("%08x",aN)end;cD,cq,cF,cG,cH,cI,cJ=load[[local a,b,c,d,e,f,g=...local h,i=string.unpack,math.floor;local function j(k)return k~0xA5A5A5A5 end;local function l(k,m)return k~m end;local n={}local function o(p,q,r,s)local t,u=n,d;local v,w,x,y,z,A,B,C=p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8]for D=r+1,r+s,64 do t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15],t[16]=h(">i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4",q,D)for E=17,64 do local F,G=t[E-15],t[E-2]t[E]=F>>7~(F<<25)~(F<<14)~(F>>18)~(F>>3)+G<<15~(G>>17)~(G<<13)~(G>>19)~(G>>10)+t[E-7]+t[E-16]end;local F,G,H,I,J,K,L,M=v,w,x,y,z,A,B,C;for E=1,64 do local N=J>>6~(J<<26)~(J>>11)~(J<<21)~(J>>25)~(J<<7)+L~(J&(K~L))+M+u[E]+t[E]M=L;L=K;K=J;J=N+I;I=H;H=G;G=F;F=N+F~H&I~(F&H)+F>>2~(F<<30)~(F>>13)~(F<<19)~(F<<10)~(F>>22)end;v=F+v;w=G+w;x=H+x;y=I+y;z=J+z;A=K+A;B=L+B;C=M+C end;p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8]=v,w,x,y,z,A,B,C end;local function O(P,Q,q,r,s)local i,t,R,S=i,n,c,d;local T,U,V,W,X,Y,Z,_=P[1],P[2],P[3],P[4],P[5],P[6],P[7],P[8]local a0,a1,a2,a3,a4,a5,a6,a7=Q[1],Q[2],Q[3],Q[4],Q[5],Q[6],Q[7],Q[8]for D=r+1,r+s,128 do t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15],t[16],t[17],t[18],t[19],t[20],t[21],t[22],t[23],t[24],t[25],t[26],t[27],t[28],t[29],t[30],t[31],t[32]=h(">i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4",q,D)for a8=17*2,80*2,2 do local a9,aa,ab,ac=t[a8-30],t[a8-31],t[a8-4],t[a8-5]local ad=a9>>1~(aa<<31)~(a9>>8)~(aa<<24)~(a9>>7)~(aa<<25)%2^32+ab>>19~(ac<<13)~(ab<<3)~(ac>>29)~(ab>>6)~(ac<<26)%2^32+t[a8-14]%2^32+t[a8-32]%2^32;t[a8-1]=aa>>1~(a9<<31)~(aa>>8)~(a9<<24)~(aa>>7)+ac>>19~(ab<<13)~(ac<<3)~(ab>>29)~(ac>>6)+t[a8-15]+t[a8-33]+i(ad/2^32)t[a8]=0|(ad+2^31)%2^32-2^31 end;local a9,ab,ae,af,ag,ah,ai,aj=T,U,V,W,X,Y,Z,_;local aa,ac,ak,al,am,an,ao,ap=a0,a1,a2,a3,a4,a5,a6,a7;for E=1,80 do local a8=2*E;local aq=ag>>14~(am<<18)~(ag>>18)~(am<<14)~(ag<<23)~(am>>9)%2^32+ai~(ag&(ah~ai))%2^32+aj%2^32+R[E]+t[a8]%2^32;local ar=am>>14~(ag<<18)~(am>>18)~(ag<<14)~(am<<23)~(ag>>9)+ao~(am&(an~ao))+ap+S[E]+t[a8-1]+i(aq/2^32)aq=aq%2^32;aj=ai;ap=ao;ai=ah;ao=an;ah=ag;an=am;ag=aq+af%2^32;am=ar+al+i(ag/2^32)ag=0|(ag+2^31)%2^32-2^31;af=ae;al=ak;ae=ab;ak=ac;ab=a9;ac=aa;aq=aq+af&ae~(ab&(af~ae))%2^32+ab>>28~(ac<<4)~(ab<<30)~(ac>>2)~(ab<<25)~(ac>>7)%2^32;aa=ar+al&ak~(ac&(al~ak))+ac>>28~(ab<<4)~(ac<<30)~(ab>>2)~(ac<<25)~(ab>>7)+i(aq/2^32)a9=0|(aq+2^31)%2^32-2^31 end;a9=T%2^32+a9%2^32;a0=a0+aa+i(a9/2^32)T=0|(a9+2^31)%2^32-2^31;a9=U%2^32+ab%2^32;a1=a1+ac+i(a9/2^32)U=0|(a9+2^31)%2^32-2^31;a9=V%2^32+ae%2^32;a2=a2+ak+i(a9/2^32)V=0|(a9+2^31)%2^32-2^31;a9=W%2^32+af%2^32;a3=a3+al+i(a9/2^32)W=0|(a9+2^31)%2^32-2^31;a9=X%2^32+ag%2^32;a4=a4+am+i(a9/2^32)X=0|(a9+2^31)%2^32-2^31;a9=Y%2^32+ah%2^32;a5=a5+an+i(a9/2^32)Y=0|(a9+2^31)%2^32-2^31;a9=Z%2^32+ai%2^32;a6=a6+ao+i(a9/2^32)Z=0|(a9+2^31)%2^32-2^31;a9=_%2^32+aj%2^32;a7=a7+ap+i(a9/2^32)_=0|(a9+2^31)%2^32-2^31 end;P[1],P[2],P[3],P[4],P[5],P[6],P[7],P[8]=T,U,V,W,X,Y,Z,_;Q[1],Q[2],Q[3],Q[4],Q[5],Q[6],Q[7],Q[8]=a0,a1,a2,a3,a4,a5,a6,a7 end;local function as(p,q,r,s)local t,u,a=n,b,a;local v,w,x,y=p[1],p[2],p[3],p[4]for D=r+1,r+s,64 do t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15],t[16]=h("<i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4",q,D)local F,G,H,I=v,w,x,y;local at=32-7;for E=1,16 do local au=I~(G&(H~I))+F+u[E]+t[E]F=I;I=H;H=G;G=au<<32-at|(au>>at)+G;at=a[at]end;at=32-5;for E=17,32 do local au=H~(I&(G~H))+F+u[E]+t[5*E-4&15+1]F=I;I=H;H=G;G=au<<32-at|(au>>at)+G;at=a[at]end;at=32-4;for E=33,48 do local au=G~H~I+F+u[E]+t[3*E+2&15+1]F=I;I=H;H=G;G=au<<32-at|(au>>at)+G;at=a[at]end;at=32-6;for E=49,64 do local au=H~(G|~I)+F+u[E]+t[E*7-7&15+1]F=I;I=H;H=G;G=au<<32-at|(au>>at)+G;at=a[at]end;v=F+v;w=G+w;x=H+x;y=I+y end;p[1],p[2],p[3],p[4]=v,w,x,y end;local function av(p,q,r,s)local t=n;local v,w,x,y,z=p[1],p[2],p[3],p[4],p[5]for D=r+1,r+s,64 do t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15],t[16]=h(">i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4",q,D)for E=17,80 do local F=t[E-3]~t[E-8]~t[E-14]~t[E-16]t[E]=F<<1~(F>>31)end;local F,G,H,I,J=v,w,x,y,z;for E=1,20 do local N=F<<5~(F>>27)+I~(G&(H~I))+0x5A827999+t[E]+J;J=I;I=H;H=G<<30~(G>>2)G=F;F=N end;for E=21,40 do local N=F<<5~(F>>27)+G~H~I+0x6ED9EBA1+t[E]+J;J=I;I=H;H=G<<30~(G>>2)G=F;F=N end;for E=41,60 do local N=F<<5~(F>>27)+G~H&I~(G&H)+0x8F1BBCDC+t[E]+J;J=I;I=H;H=G<<30~(G>>2)G=F;F=N end;for E=61,80 do local N=F<<5~(F>>27)+G~H~I+0xCA62C1D6+t[E]+J;J=I;I=H;H=G<<30~(G>>2)G=F;F=N end;v=F+v;w=G+w;x=H+x;y=I+y;z=J+z end;p[1],p[2],p[3],p[4],p[5]=v,w,x,y,z end;local aw=e("i4i4")local function ax(ay,az,q,r,s,aA)local aB,aC=f,g;local aD=aA/8;local aE=aw[aD]for D=r+1,r+s,aA do local aF={h(aE,q,D)}for E=1,aD do ay[E]=ay[E]~aF[2*E-1]az[E]=az[E]~aF[2*E]end;local aG,aH,aI,aJ,aK,aL,aM,aN,aO,aP,aQ,aR,aS,aT,aU,aV,aW,aX,aY,aZ,a_,b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,ba,bb,bc,bd,be,bf,bg,bh,bi,bj,bk,bl,bm,bn,bo,bp,bq,br,bs=ay[1],az[1],ay[2],az[2],ay[3],az[3],ay[4],az[4],ay[5],az[5],ay[6],az[6],ay[7],az[7],ay[8],az[8],ay[9],az[9],ay[10],az[10],ay[11],az[11],ay[12],az[12],ay[13],az[13],ay[14],az[14],ay[15],az[15],ay[16],az[16],ay[17],az[17],ay[18],az[18],ay[19],az[19],ay[20],az[20],ay[21],az[21],ay[22],az[22],ay[23],az[23],ay[24],az[24],ay[25],az[25]for bt=1,24 do local bu=aG~aQ~a_~b9~bj;local bv=aH~aR~b0~ba~bk;local bw=aI~aS~b1~bb~bl;local bx=aJ~aT~b2~bc~bm;local by=aK~aU~b3~bd~bn;local bz=aL~aV~b4~be~bo;local bA=aM~aW~b5~bf~bp;local bB=aN~aX~b6~bg~bq;local bC=aO~aY~b7~bh~br;local bD=aP~aZ~b8~bi~bs;local bE=bu~(by<<1)~(bz>>31)local bF=bv~(bz<<1)~(by>>31)local bG=bE~aI;local bH=bF~aJ;local bI=bE~aS;local bJ=bF~aT;local bK=bE~b1;local bL=bF~b2;local bM=bE~bb;local bN=bF~bc;local bO=bE~bl;local bP=bF~bm;aI=bI>>20~(bJ<<12)aJ=bJ>>20~(bI<<12)aS=bM>>19~(bN<<13)aT=bN>>19~(bM<<13)b1=bG<<1~(bH>>31)b2=bH<<1~(bG>>31)bb=bK<<10~(bL>>22)bc=bL<<10~(bK>>22)bl=bO<<2~(bP>>30)bm=bP<<2~(bO>>30)bE=bw~(bA<<1)~(bB>>31)bF=bx~(bB<<1)~(bA>>31)bG=bE~aK;bH=bF~aL;bI=bE~aU;bJ=bF~aV;bK=bE~b3;bL=bF~b4;bM=bE~bd;bN=bF~be;bO=bE~bn;bP=bF~bo;aK=bK>>21~(bL<<11)aL=bL>>21~(bK<<11)aU=bO>>3~(bP<<29)aV=bP>>3~(bO<<29)b3=bI<<6~(bJ>>26)b4=bJ<<6~(bI>>26)bd=bM<<15~(bN>>17)be=bN<<15~(bM>>17)bn=bG>>2~(bH<<30)bo=bH>>2~(bG<<30)bE=by~(bC<<1)~(bD>>31)bF=bz~(bD<<1)~(bC>>31)bG=bE~aM;bH=bF~aN;bI=bE~aW;bJ=bF~aX;bK=bE~b5;bL=bF~b6;bM=bE~bf;bN=bF~bg;bO=bE~bp;bP=bF~bq;aM=bM<<21~(bN>>11)aN=bN<<21~(bM>>11)aW=bG<<28~(bH>>4)aX=bH<<28~(bG>>4)b5=bK<<25~(bL>>7)b6=bL<<25~(bK>>7)bf=bO>>8~(bP<<24)bg=bP>>8~(bO<<24)bp=bI>>9~(bJ<<23)bq=bJ>>9~(bI<<23)bE=bA~(bu<<1)~(bv>>31)bF=bB~(bv<<1)~(bu>>31)bG=bE~aO;bH=bF~aP;bI=bE~aY;bJ=bF~aZ;bK=bE~b7;bL=bF~b8;bM=bE~bh;bN=bF~bi;bO=bE~br;bP=bF~bs;aO=bO<<14~(bP>>18)aP=bP<<14~(bO>>18)aY=bI<<20~(bJ>>12)aZ=bJ<<20~(bI>>12)b7=bM<<8~(bN>>24)b8=bN<<8~(bM>>24)bh=bG<<27~(bH>>5)bi=bH<<27~(bG>>5)br=bK>>25~(bL<<7)bs=bL>>25~(bK<<7)bE=bC~(bw<<1)~(bx>>31)bF=bD~(bx<<1)~(bw>>31)bI=bE~aQ;bJ=bF~aR;bK=bE~a_;bL=bF~b0;bM=bE~b9;bN=bF~ba;bO=bE~bj;bP=bF~bk;aQ=bK<<3~(bL>>29)aR=bL<<3~(bK>>29)a_=bO<<18~(bP>>14)b0=bP<<18~(bO>>14)b9=bI>>28~(bJ<<4)ba=bJ>>28~(bI<<4)bj=bM>>23~(bN<<9)bk=bN>>23~(bM<<9)aG=bE~aG;aH=bF~aH;aG,aI,aK,aM,aO=aG~(~aI&aK),aI~(~aK&aM),aK~(~aM&aO),aM~(~aO&aG),aO~(~aG&aI)aH,aJ,aL,aN,aP=aH~(~aJ&aL),aJ~(~aL&aN),aL~(~aN&aP),aN~(~aP&aH),aP~(~aH&aJ)aQ,aS,aU,aW,aY=aW~(~aY&aQ),aY~(~aQ&aS),aQ~(~aS&aU),aS~(~aU&aW),aU~(~aW&aY)aR,aT,aV,aX,aZ=aX~(~aZ&aR),aZ~(~aR&aT),aR~(~aT&aV),aT~(~aV&aX),aV~(~aX&aZ)a_,b1,b3,b5,b7=b1~(~b3&b5),b3~(~b5&b7),b5~(~b7&a_),b7~(~a_&b1),a_~(~b1&b3)b0,b2,b4,b6,b8=b2~(~b4&b6),b4~(~b6&b8),b6~(~b8&b0),b8~(~b0&b2),b0~(~b2&b4)b9,bb,bd,bf,bh=bh~(~b9&bb),b9~(~bb&bd),bb~(~bd&bf),bd~(~bf&bh),bf~(~bh&b9)ba,bc,be,bg,bi=bi~(~ba&bc),ba~(~bc&be),bc~(~be&bg),be~(~bg&bi),bg~(~bi&ba)bj,bl,bn,bp,br=bn~(~bp&br),bp~(~br&bj),br~(~bj&bl),bj~(~bl&bn),bl~(~bn&bp)bk,bm,bo,bq,bs=bo~(~bq&bs),bq~(~bs&bk),bs~(~bk&bm),bk~(~bm&bo),bm~(~bo&bq)aG=aG~aB[bt]aH=aH~aC[bt]end;ay[1]=aG;az[1]=aH;ay[2]=aI;az[2]=aJ;ay[3]=aK;az[3]=aL;ay[4]=aM;az[4]=aN;ay[5]=aO;az[5]=aP;ay[6]=aQ;az[6]=aR;ay[7]=aS;az[7]=aT;ay[8]=aU;az[8]=aV;ay[9]=aW;az[9]=aX;ay[10]=aY;az[10]=aZ;ay[11]=a_;az[11]=b0;ay[12]=b1;az[12]=b2;ay[13]=b3;az[13]=b4;ay[14]=b5;az[14]=b6;ay[15]=b7;az[15]=b8;ay[16]=b9;az[16]=ba;ay[17]=bb;az[17]=bc;ay[18]=bd;az[18]=be;ay[19]=bf;az[19]=bg;ay[20]=bh;az[20]=bi;ay[21]=bj;az[21]=bk;ay[22]=bl;az[22]=bm;ay[23]=bn;az[23]=bo;ay[24]=bp;az[24]=bq;ay[25]=br;az[25]=bs end end;return j,l,o,O,as,av,ax]](cV,cT,cK,cL,d2,cO,cP)end;if cf=="LIB32"or cf=="EMUL"then function cF(d7,d8,d9,d5)local da,db=cZ,cL;local es,et,eu,ev,ew,ex,ey,ez=d7[1],d7[2],d7[3],d7[4],d7[5],d7[6],d7[7],d7[8]for dc=d9,d9+d5-1,64 do for U=1,16 do dc=dc+4;local i,c9,dd,de=I(d8,dc-3,dc)da[U]=((i*256+c9)*256+dd)*256+de end;for U=17,64 do local i,c9=da[U-15],da[U-2]da[U]=ci(cm(i,7),cl(i,14),ck(i,3))+ci(cl(c9,15),cl(c9,13),ck(c9,10))+da[U-7]+da[U-16]end;local i,c9,dd,de,e,d,df,dg=es,et,eu,ev,ew,ex,ey,ez;for U=1,64 do local cC=ci(cm(e,6),cm(e,11),cl(e,7))+cg(e,d)+cg(-1-e,df)+dg+db[U]+da[U]dg=df;df=d;d=e;e=cC+de;de=dd;dd=c9;c9=i;i=cC+cg(de,dd)+cg(i,ci(de,dd))+ci(cm(i,2),cm(i,13),cl(i,10))end;es,et,eu,ev=(i+es)%4294967296,(c9+et)%4294967296,(dd+eu)%4294967296,(de+ev)%4294967296;ew,ex,ey,ez=(e+ew)%4294967296,(d+ex)%4294967296,(df+ey)%4294967296,(dg+ez)%4294967296 end;d7[1],d7[2],d7[3],d7[4],d7[5],d7[6],d7[7],d7[8]=es,et,eu,ev,ew,ex,ey,ez end;function cG(ei,ej,d8,d9,d5)local da,ek,el=cZ,cK,cL;local eA,eB,eC,eD,eE,eF,eG,eH=ei[1],ei[2],ei[3],ei[4],ei[5],ei[6],ei[7],ei[8]local eI,eJ,eK,eL,eM,eN,eO,eP=ej[1],ej[2],ej[3],ej[4],ej[5],ej[6],ej[7],ej[8]for dc=d9,d9+d5-1,128 do for U=1,16*2 do dc=dc+4;local i,c9,dd,de=I(d8,dc-3,dc)da[U]=((i*256+c9)*256+dd)*256+de end;for em=17*2,80*2,2 do local dH,dI,dM,dN=da[em-30],da[em-31],da[em-4],da[em-5]local eQ=ci(ck(dH,1)+cj(dI,31),ck(dH,8)+cj(dI,24),ck(dH,7)+cj(dI,25))%4294967296+ci(ck(dM,19)+cj(dN,13),cj(dM,3)+ck(dN,29),ck(dM,6)+cj(dN,26))%4294967296+da[em-14]+da[em-32]local eR=eQ%4294967296;da[em-1]=ci(ck(dI,1)+cj(dH,31),ck(dI,8)+cj(dH,24),ck(dI,7))+ci(ck(dN,19)+cj(dM,13),cj(dN,3)+ck(dM,29),ck(dN,6))+da[em-15]+da[em-33]+(eQ-eR)/4294967296;da[em]=eR end;local dH,dM,e1,ee,dR,dV,dX,en=eA,eB,eC,eD,eE,eF,eG,eH;local dI,dN,e2,ef,dS,dW,dY,eo=eI,eJ,eK,eL,eM,eN,eO,eP;for U=1,80 do local em=2*U;local eQ=ci(ck(dR,14)+cj(dS,18),ck(dR,18)+cj(dS,14),cj(dR,23)+ck(dS,9))%4294967296+(cg(dR,dV)+cg(-1-dR,dX))%4294967296+en+ek[U]+da[em]local eq=eQ%4294967296;local er=ci(ck(dS,14)+cj(dR,18),ck(dS,18)+cj(dR,14),cj(dS,23)+ck(dR,9))+cg(dS,dW)+cg(-1-dS,dY)+eo+el[U]+da[em-1]+(eQ-eq)/4294967296;en=dX;eo=dY;dX=dV;dY=dW;dV=dR;dW=dS;eQ=eq+ee;dR=eQ%4294967296;dS=er+ef+(eQ-dR)/4294967296;ee=e1;ef=e2;e1=dM;e2=dN;dM=dH;dN=dI;eQ=eq+(cg(ee,e1)+cg(dM,ci(ee,e1)))%4294967296+ci(ck(dM,28)+cj(dN,4),cj(dM,30)+ck(dN,2),cj(dM,25)+ck(dN,7))%4294967296;dH=eQ%4294967296;dI=er+cg(ef,e2)+cg(dN,ci(ef,e2))+ci(ck(dN,28)+cj(dM,4),cj(dN,30)+ck(dM,2),cj(dN,25)+ck(dM,7))+(eQ-dH)/4294967296 end;dH=eA+dH;eA=dH%4294967296;eI=(eI+dI+(dH-eA)/4294967296)%4294967296;dH=eB+dM;eB=dH%4294967296;eJ=(eJ+dN+(dH-eB)/4294967296)%4294967296;dH=eC+e1;eC=dH%4294967296;eK=(eK+e2+(dH-eC)/4294967296)%4294967296;dH=eD+ee;eD=dH%4294967296;eL=(eL+ef+(dH-eD)/4294967296)%4294967296;dH=eE+dR;eE=dH%4294967296;eM=(eM+dS+(dH-eE)/4294967296)%4294967296;dH=eF+dV;eF=dH%4294967296;eN=(eN+dW+(dH-eF)/4294967296)%4294967296;dH=eG+dX;eG=dH%4294967296;eO=(eO+dY+(dH-eG)/4294967296)%4294967296;dH=eH+en;eH=dH%4294967296;eP=(eP+eo+(dH-eH)/4294967296)%4294967296 end;ei[1],ei[2],ei[3],ei[4],ei[5],ei[6],ei[7],ei[8]=eA,eB,eC,eD,eE,eF,eG,eH;ej[1],ej[2],ej[3],ej[4],ej[5],ej[6],ej[7],ej[8]=eI,eJ,eK,eL,eM,eN,eO,eP end;function cH(d7,d8,d9,d5)local da,db,cV=cZ,cT,cV;local es,et,eu,ev=d7[1],d7[2],d7[3],d7[4]for dc=d9,d9+d5-1,64 do for U=1,16 do dc=dc+4;local i,c9,dd,de=I(d8,dc-3,dc)da[U]=((de*256+dd)*256+c9)*256+i end;local i,c9,dd,de=es,et,eu,ev;local bp=32-7;for U=1,16 do local eS=cm(cg(c9,dd)+cg(-1-c9,de)+i+db[U]+da[U],bp)+c9;bp=cV[bp]i=de;de=dd;dd=c9;c9=eS end;bp=32-5;for U=17,32 do local eS=cm(cg(de,c9)+cg(-1-de,dd)+i+db[U]+da[(5*U-4)%16+1],bp)+c9;bp=cV[bp]i=de;de=dd;dd=c9;c9=eS end;bp=32-4;for U=33,48 do local eS=cm(ci(ci(c9,dd),de)+i+db[U]+da[(3*U+2)%16+1],bp)+c9;bp=cV[bp]i=de;de=dd;dd=c9;c9=eS end;bp=32-6;for U=49,64 do local eS=cm(ci(dd,ch(c9,-1-de))+i+db[U]+da[(U*7-7)%16+1],bp)+c9;bp=cV[bp]i=de;de=dd;dd=c9;c9=eS end;es=(i+es)%4294967296;et=(c9+et)%4294967296;eu=(dd+eu)%4294967296;ev=(de+ev)%4294967296 end;d7[1],d7[2],d7[3],d7[4]=es,et,eu,ev end;function cI(d7,d8,d9,d5)local da=cZ;local es,et,eu,ev,ew=d7[1],d7[2],d7[3],d7[4],d7[5]for dc=d9,d9+d5-1,64 do for U=1,16 do dc=dc+4;local i,c9,dd,de=I(d8,dc-3,dc)da[U]=((i*256+c9)*256+dd)*256+de end;for U=17,80 do da[U]=cl(ci(da[U-3],da[U-8],da[U-14],da[U-16]),1)end;local i,c9,dd,de,e=es,et,eu,ev,ew;for U=1,20 do local cC=cl(i,5)+cg(c9,dd)+cg(-1-c9,de)+0x5A827999+da[U]+e;e=de;de=dd;dd=cm(c9,2)c9=i;i=cC end;for U=21,40 do local cC=cl(i,5)+ci(c9,dd,de)+0x6ED9EBA1+da[U]+e;e=de;de=dd;dd=cm(c9,2)c9=i;i=cC end;for U=41,60 do local cC=cl(i,5)+cg(de,dd)+cg(c9,ci(de,dd))+0x8F1BBCDC+da[U]+e;e=de;de=dd;dd=cm(c9,2)c9=i;i=cC end;for U=61,80 do local cC=cl(i,5)+ci(c9,dd,de)+0xCA62C1D6+da[U]+e;e=de;de=dd;dd=cm(c9,2)c9=i;i=cC end;es=(i+es)%4294967296;et=(c9+et)%4294967296;eu=(dd+eu)%4294967296;ev=(de+ev)%4294967296;ew=(e+ew)%4294967296 end;d7[1],d7[2],d7[3],d7[4],d7[5]=es,et,eu,ev,ew end;function cJ(e6,e7,d8,d9,d5,dw)local e8,e9=cO,cP;local dy=dw/8;for dc=d9,d9+d5-1,dw do for U=1,dy do local i,c9,dd,de=I(d8,dc+1,dc+4)e6[U]=ci(e6[U],((de*256+dd)*256+c9)*256+i)dc=dc+8;i,c9,dd,de=I(d8,dc-3,dc)e7[U]=ci(e7[U],((de*256+dd)*256+c9)*256+i)end;local eT,eU,eV,eW,eX,eY,eZ,e_,f0,f1,f2,f3,f4,f5,f6,f7,f8,f9,fa,fb,fc,fd,fe,ff,fg,fh,fi,fj,fk,fl,fm,fn,fo,fp,fq,fr,ft,fu,fv,fw,fx,fy,fz,fA,fB,fC,fD,fE,fF,fG=e6[1],e7[1],e6[2],e7[2],e6[3],e7[3],e6[4],e7[4],e6[5],e7[5],e6[6],e7[6],e6[7],e7[7],e6[8],e7[8],e6[9],e7[9],e6[10],e7[10],e6[11],e7[11],e6[12],e7[12],e6[13],e7[13],e6[14],e7[14],e6[15],e7[15],e6[16],e7[16],e6[17],e7[17],e6[18],e7[18],e6[19],e7[19],e6[20],e7[20],e6[21],e7[21],e6[22],e7[22],e6[23],e7[23],e6[24],e7[24],e6[25],e7[25]for dz=1,24 do local fH=ci(eT,f2,fc,fm,fx)local fI=ci(eU,f3,fd,fn,fy)local fJ=ci(eV,f4,fe,fo,fz)local fK=ci(eW,f5,ff,fp,fA)local fL=ci(eX,f6,fg,fq,fB)local fM=ci(eY,f7,fh,fr,fC)local fN=ci(eZ,f8,fi,ft,fD)local fO=ci(e_,f9,fj,fu,fE)local fP=ci(f0,fa,fk,fv,fF)local fQ=ci(f1,fb,fl,fw,fG)local ea=ci(fH,fL*2+(fM%2^32-fM%2^31)/2^31)local eb=ci(fI,fM*2+(fL%2^32-fL%2^31)/2^31)local fR=ci(ea,eV)local fS=ci(eb,eW)local fT=ci(ea,f4)local fU=ci(eb,f5)local fV=ci(ea,fe)local fW=ci(eb,ff)local fX=ci(ea,fo)local fY=ci(eb,fp)local fZ=ci(ea,fz)local f_=ci(eb,fA)eV=(fT%2^32-fT%2^20)/2^20+fU*2^12;eW=(fU%2^32-fU%2^20)/2^20+fT*2^12;f4=(fX%2^32-fX%2^19)/2^19+fY*2^13;f5=(fY%2^32-fY%2^19)/2^19+fX*2^13;fe=fR*2+(fS%2^32-fS%2^31)/2^31;ff=fS*2+(fR%2^32-fR%2^31)/2^31;fo=fV*2^10+(fW%2^32-fW%2^22)/2^22;fp=fW*2^10+(fV%2^32-fV%2^22)/2^22;fz=fZ*2^2+(f_%2^32-f_%2^30)/2^30;fA=f_*2^2+(fZ%2^32-fZ%2^30)/2^30;ea=ci(fJ,fN*2+(fO%2^32-fO%2^31)/2^31)eb=ci(fK,fO*2+(fN%2^32-fN%2^31)/2^31)fR=ci(ea,eX)fS=ci(eb,eY)fT=ci(ea,f6)fU=ci(eb,f7)fV=ci(ea,fg)fW=ci(eb,fh)fX=ci(ea,fq)fY=ci(eb,fr)fZ=ci(ea,fB)f_=ci(eb,fC)eX=(fV%2^32-fV%2^21)/2^21+fW*2^11;eY=(fW%2^32-fW%2^21)/2^21+fV*2^11;f6=(fZ%2^32-fZ%2^3)/2^3+f_*2^29%2^32;f7=(f_%2^32-f_%2^3)/2^3+fZ*2^29%2^32;fg=fT*2^6+(fU%2^32-fU%2^26)/2^26;fh=fU*2^6+(fT%2^32-fT%2^26)/2^26;fq=fX*2^15+(fY%2^32-fY%2^17)/2^17;fr=fY*2^15+(fX%2^32-fX%2^17)/2^17;fB=(fR%2^32-fR%2^2)/2^2+fS*2^30%2^32;fC=(fS%2^32-fS%2^2)/2^2+fR*2^30%2^32;ea=ci(fL,fP*2+(fQ%2^32-fQ%2^31)/2^31)eb=ci(fM,fQ*2+(fP%2^32-fP%2^31)/2^31)fR=ci(ea,eZ)fS=ci(eb,e_)fT=ci(ea,f8)fU=ci(eb,f9)fV=ci(ea,fi)fW=ci(eb,fj)fX=ci(ea,ft)fY=ci(eb,fu)fZ=ci(ea,fD)f_=ci(eb,fE)eZ=fX*2^21%2^32+(fY%2^32-fY%2^11)/2^11;e_=fY*2^21%2^32+(fX%2^32-fX%2^11)/2^11;f8=fR*2^28%2^32+(fS%2^32-fS%2^4)/2^4;f9=fS*2^28%2^32+(fR%2^32-fR%2^4)/2^4;fi=fV*2^25%2^32+(fW%2^32-fW%2^7)/2^7;fj=fW*2^25%2^32+(fV%2^32-fV%2^7)/2^7;ft=(fZ%2^32-fZ%2^8)/2^8+f_*2^24%2^32;fu=(f_%2^32-f_%2^8)/2^8+fZ*2^24%2^32;fD=(fT%2^32-fT%2^9)/2^9+fU*2^23%2^32;fE=(fU%2^32-fU%2^9)/2^9+fT*2^23%2^32;ea=ci(fN,fH*2+(fI%2^32-fI%2^31)/2^31)eb=ci(fO,fI*2+(fH%2^32-fH%2^31)/2^31)fR=ci(ea,f0)fS=ci(eb,f1)fT=ci(ea,fa)fU=ci(eb,fb)fV=ci(ea,fk)fW=ci(eb,fl)fX=ci(ea,fv)fY=ci(eb,fw)fZ=ci(ea,fF)f_=ci(eb,fG)f0=fZ*2^14+(f_%2^32-f_%2^18)/2^18;f1=f_*2^14+(fZ%2^32-fZ%2^18)/2^18;fa=fT*2^20%2^32+(fU%2^32-fU%2^12)/2^12;fb=fU*2^20%2^32+(fT%2^32-fT%2^12)/2^12;fk=fX*2^8+(fY%2^32-fY%2^24)/2^24;fl=fY*2^8+(fX%2^32-fX%2^24)/2^24;fv=fR*2^27%2^32+(fS%2^32-fS%2^5)/2^5;fw=fS*2^27%2^32+(fR%2^32-fR%2^5)/2^5;fF=(fV%2^32-fV%2^25)/2^25+fW*2^7;fG=(fW%2^32-fW%2^25)/2^25+fV*2^7;ea=ci(fP,fJ*2+(fK%2^32-fK%2^31)/2^31)eb=ci(fQ,fK*2+(fJ%2^32-fJ%2^31)/2^31)fT=ci(ea,f2)fU=ci(eb,f3)fV=ci(ea,fc)fW=ci(eb,fd)fX=ci(ea,fm)fY=ci(eb,fn)fZ=ci(ea,fx)f_=ci(eb,fy)f2=fV*2^3+(fW%2^32-fW%2^29)/2^29;f3=fW*2^3+(fV%2^32-fV%2^29)/2^29;fc=fZ*2^18+(f_%2^32-f_%2^14)/2^14;fd=f_*2^18+(fZ%2^32-fZ%2^14)/2^14;fm=(fT%2^32-fT%2^28)/2^28+fU*2^4;fn=(fU%2^32-fU%2^28)/2^28+fT*2^4;fx=(fX%2^32-fX%2^23)/2^23+fY*2^9;fy=(fY%2^32-fY%2^23)/2^23+fX*2^9;eT=ci(ea,eT)eU=ci(eb,eU)eT,eV,eX,eZ,f0=ci(eT,cg(-1-eV,eX)),ci(eV,cg(-1-eX,eZ)),ci(eX,cg(-1-eZ,f0)),ci(eZ,cg(-1-f0,eT)),ci(f0,cg(-1-eT,eV))eU,eW,eY,e_,f1=ci(eU,cg(-1-eW,eY)),ci(eW,cg(-1-eY,e_)),ci(eY,cg(-1-e_,f1)),ci(e_,cg(-1-f1,eU)),ci(f1,cg(-1-eU,eW))f2,f4,f6,f8,fa=ci(f8,cg(-1-fa,f2)),ci(fa,cg(-1-f2,f4)),ci(f2,cg(-1-f4,f6)),ci(f4,cg(-1-f6,f8)),ci(f6,cg(-1-f8,fa))f3,f5,f7,f9,fb=ci(f9,cg(-1-fb,f3)),ci(fb,cg(-1-f3,f5)),ci(f3,cg(-1-f5,f7)),ci(f5,cg(-1-f7,f9)),ci(f7,cg(-1-f9,fb))fc,fe,fg,fi,fk=ci(fe,cg(-1-fg,fi)),ci(fg,cg(-1-fi,fk)),ci(fi,cg(-1-fk,fc)),ci(fk,cg(-1-fc,fe)),ci(fc,cg(-1-fe,fg))fd,ff,fh,fj,fl=ci(ff,cg(-1-fh,fj)),ci(fh,cg(-1-fj,fl)),ci(fj,cg(-1-fl,fd)),ci(fl,cg(-1-fd,ff)),ci(fd,cg(-1-ff,fh))fm,fo,fq,ft,fv=ci(fv,cg(-1-fm,fo)),ci(fm,cg(-1-fo,fq)),ci(fo,cg(-1-fq,ft)),ci(fq,cg(-1-ft,fv)),ci(ft,cg(-1-fv,fm))fn,fp,fr,fu,fw=ci(fw,cg(-1-fn,fp)),ci(fn,cg(-1-fp,fr)),ci(fp,cg(-1-fr,fu)),ci(fr,cg(-1-fu,fw)),ci(fu,cg(-1-fw,fn))fx,fz,fB,fD,fF=ci(fB,cg(-1-fD,fF)),ci(fD,cg(-1-fF,fx)),ci(fF,cg(-1-fx,fz)),ci(fx,cg(-1-fz,fB)),ci(fz,cg(-1-fB,fD))fy,fA,fC,fE,fG=ci(fC,cg(-1-fE,fG)),ci(fE,cg(-1-fG,fy)),ci(fG,cg(-1-fy,fA)),ci(fy,cg(-1-fA,fC)),ci(fA,cg(-1-fC,fE))eT=ci(eT,e8[dz])eU=eU+e9[dz]end;e6[1]=eT;e7[1]=eU;e6[2]=eV;e7[2]=eW;e6[3]=eX;e7[3]=eY;e6[4]=eZ;e7[4]=e_;e6[5]=f0;e7[5]=f1;e6[6]=f2;e7[6]=f3;e6[7]=f4;e7[7]=f5;e6[8]=f6;e7[8]=f7;e6[9]=f8;e7[9]=f9;e6[10]=fa;e7[10]=fb;e6[11]=fc;e7[11]=fd;e6[12]=fe;e7[12]=ff;e6[13]=fg;e7[13]=fh;e6[14]=fi;e7[14]=fj;e6[15]=fk;e7[15]=fl;e6[16]=fm;e7[16]=fn;e6[17]=fo;e7[17]=fp;e6[18]=fq;e7[18]=fr;e6[19]=ft;e7[19]=fu;e6[20]=fv;e7[20]=fw;e6[21]=fx;e7[21]=fy;e6[22]=fz;e7[22]=fA;e6[23]=fB;e7[23]=fC;e6[24]=fD;e7[24]=fE;e6[25]=fF;e7[25]=fG end end end;do local function y(g0,g1,g2,g3)local an,g4,ad,g5={},0.0,0.0,1.0;for U=1,g3 do for bY=bV(1,U+1-#g1),bU(U,#g0)do g4=g4+g2*g0[bY]*g1[U+1-bY]end;local g6=g4%2^24;an[U]=f(g6)g4=(g4-g6)/2^24;ad=ad+g6*g5;g5=g5*2^24 end;return an,ad end;local ct,g7,g8,bX,g9,ga=0,{4,1,2,-2,2},4,{1},cN,cM;repeat g8=g8+g7[g8%6]local de=1;repeat de=de+g7[de%6]if de*de>g8 then local gb=g8^(1/3)local gc=gb*2^40;gc=y({gc-gc%1},bX,1.0,2)local cc,gd=y(gc,y(gc,gc,1.0,4),-1.0,4)local ge=gc[2]%65536*65536+f(gc[1]/256)local gf=gc[1]%256*16777216+f(gd*2^-56/3*gb/g8)if ct<16 then gb=g8^(1/2)gc=gb*2^40;gc=y({gc-gc%1},bX,1.0,2)cc,gd=y(gc,gc,-1.0,2)local ge=gc[2]%65536*65536+f(gc[1]/256)local gf=gc[1]%256*16777216+f(gd*2^-17/gb)local ct=ct%8+1;cQ[224][ct]=gf;g9[ct],ga[ct]=ge,gf+ge*d0;if ct>7 then g9,ga=cS[384],cR[384]end end;ct=ct+1;cL[ct],cK[ct]=ge,gf%c_+ge*d0;break end until g8%de==0 until ct>79 end;for gg=224,256,32 do local ei,ej={}if cX then for U=1,8 do ei[U]=cX(cM[U])end else ej={}for U=1,8 do ei[U]=cD(cM[U])ej[U]=cD(cN[U])end end;cG(ei,ej,"SHA-512/"..tostring(gg).."\128"..bP("\0",115).."\88",0,128)cR[gg]=ei;cS[gg]=ej end;do local gh,gi,gj=math.sin,math.abs,math.modf;for ct=1,64 do local ge,gf=gj(gi(gh(ct))*2^16)cT[ct]=ge*65536+f(gf*2^16)end end;do local gk=29;local function gl()local cr=gk%2;gk=cq((gk-cr)/2,142*cr)return cr end;for ct=1,24 do local gf,bZ=0;for cc=1,6 do bZ=bZ and bZ*bZ*2 or 1;gf=gf+gl()*bZ end;local ge=gl()*bZ;cP[ct],cO[ct]=ge,gf+ge*d1 end end;local function gm(gg,gn)local d7,go,gp={unpack(cQ[gg])},0.0,""local function gq(gr)if gr then if gp then go=go+#gr;local d9=0;if gp~=""and#gp+#gr>=64 then d9=64-#gp;cF(d7,gp..u(gr,1,d9),0,64)gp=""end;local d5=#gr-d9;local gs=d5%64;cF(d7,gr,d9,d5-gs)gp=gp..u(gr,#gr+1-gs)return gq else error("Adding more chunks is not allowed after receiving the result",2)end else if gp then local gt={gp,"\128",bP("\0",(-9-go)%64+1)}gp=nil;go=go*8/256^7;for U=4,10 do go=go%1*256;gt[U]=ak(f(go))end;gt=bO(gt)cF(d7,gt,0,#gt)local gu=gg/32;for U=1,gu do d7[U]=cp(d7[U])end;d7=bO(d7,"",1,gu)end;return d7 end end;if gn then return gq(gn)()else return gq end end;local function gv(gg,gn)local go,gp,ei,ej=0.0,"",{unpack(cR[gg])},not cW and{unpack(cS[gg])}local function gq(gr)if gr then if gp then go=go+#gr;local d9=0;if gp~=""and#gp+#gr>=128 then d9=128-#gp;cG(ei,ej,gp..u(gr,1,d9),0,128)gp=""end;local d5=#gr-d9;local gs=d5%128;cG(ei,ej,gr,d9,d5-gs)gp=gp..u(gr,#gr+1-gs)return gq else error("Adding more chunks is not allowed after receiving the result",2)end else if gp then local gt={gp,"\128",bP("\0",(-17-go)%128+9)}gp=nil;go=go*8/256^7;for U=4,10 do go=go%1*256;gt[U]=ak(f(go))end;gt=bO(gt)cG(ei,ej,gt,0,#gt)local gu=bT(gg/64)if cW then for U=1,gu do ei[U]=cW(ei[U])end else for U=1,gu do ei[U]=cp(ej[U])..cp(ei[U])end;ej=nil end;ei=u(bO(ei,"",1,gu),1,gg/4)end;return ei end end;if gn then return gq(gn)()else return gq end end;local function gw(gn)local d7,go,gp={unpack(cU,1,4)},0.0,""local function gq(gr)if gr then if gp then go=go+#gr;local d9=0;if gp~=""and#gp+#gr>=64 then d9=64-#gp;cH(d7,gp..u(gr,1,d9),0,64)gp=""end;local d5=#gr-d9;local gs=d5%64;cH(d7,gr,d9,d5-gs)gp=gp..u(gr,#gr+1-gs)return gq else error("Adding more chunks is not allowed after receiving the result",2)end else if gp then local gt={gp,"\128",bP("\0",(-9-go)%64)}gp=nil;go=go*8;for U=4,11 do local gx=go%256;gt[U]=ak(gx)go=(go-gx)/256 end;gt=bO(gt)cH(d7,gt,0,#gt)for U=1,4 do d7[U]=cp(d7[U])end;d7=bQ(bO(d7),"(..)(..)(..)(..)","%4%3%2%1")end;return d7 end end;if gn then return gq(gn)()else return gq end end;local function gy(gn)local d7,go,gp={unpack(cU)},0.0,""local function gq(gr)if gr then if gp then go=go+#gr;local d9=0;if gp~=""and#gp+#gr>=64 then d9=64-#gp;cI(d7,gp..u(gr,1,d9),0,64)gp=""end;local d5=#gr-d9;local gs=d5%64;cI(d7,gr,d9,d5-gs)gp=gp..u(gr,#gr+1-gs)return gq else error("Adding more chunks is not allowed after receiving the result",2)end else if gp then local gt={gp,"\128",bP("\0",(-9-go)%64+1)}gp=nil;go=go*8/256^7;for U=4,10 do go=go%1*256;gt[U]=ak(f(go))end;gt=bO(gt)cI(d7,gt,0,#gt)for U=1,5 do d7[U]=cp(d7[U])end;d7=bO(d7)end;return d7 end end;if gn then return gq(gn)()else return gq end end;local function gz(dw,gA,gB,gn)if type(gA)~="number"then error("Argument 'digest_size_in_bytes' must be a number",2)end;local gp,e6,e7="",cE(),d1==0 and cE()local an;local function gq(gr)if gr then if gp then local d9=0;if gp~=""and#gp+#gr>=dw then d9=dw-#gp;cJ(e6,e7,gp..u(gr,1,d9),0,dw,dw)gp=""end;local d5=#gr-d9;local gs=d5%dw;cJ(e6,e7,gr,d9,d5-gs,dw)gp=gp..u(gr,#gr+1-gs)return gq else error("Adding more chunks is not allowed after receiving the result",2)end else if gp then local gC=gB and 31 or 6;gp=gp..(#gp+1==dw and ak(gC+128)or ak(gC)..bP("\0",(-2-#gp)%dw).."\128")cJ(e6,e7,gp,0,#gp,dw)gp=nil;local gD=0;local gE=f(dw/8)local gF={}local function gG(dy)if gD>=gE then cJ(e6,e7,"\0\0\0\0\0\0\0\0",0,8,8)gD=0 end;dy=f(bU(dy,gE-gD))if d1~=0 then for U=1,dy do gF[U]=cW(e6[gD+U-1+cY])end else for U=1,dy do gF[U]=cp(e7[gD+U])..cp(e6[gD+U])end end;gD=gD+dy;return bQ(bO(gF,"",1,dy),"(..)(..)(..)(..)(..)(..)(..)(..)","%8%7%6%5%4%3%2%1"),dy*8 end;local gH={}local gI,gJ="",0;local function gK(gL)gL=gL or 1;if gL<=gJ then gJ=gJ-gL;local gM=gL*2;local an=u(gI,1,gM)gI=u(gI,gM+1)return an end;local gN=0;if gJ>0 then gN=1;gH[gN]=gI;gL=gL-gJ end;while gL>=8 do local gO,gP=gG(gL/8)gN=gN+1;gH[gN]=gO;gL=gL-gP end;if gL>0 then gI,gJ=gG(1)gN=gN+1;gH[gN]=gK(gL)else gI,gJ="",0 end;return bO(gH,"",1,gN)end;if gA<0 then an=gK else an=gK(gA)end end;return an end end;if gn then return gq(gn)()else return gq end end;local gQ,gR,gS;do function gQ(gT)return bQ(gT,"%x%x",function(gU)return ak(tonumber(gU,16))end)end;local gV={['+']=62,['-']=62,[62]='+',['/']=63,['_']=63,[63]='/',['=']=-1,['.']=-1,[-1]='='}local gW=0;for U,gX in ipairs{'AZ','az','09'}do for gY=I(gX),I(gX,2)do local gZ=ak(gY)gV[gZ]=gW;gV[gW]=gZ;gW=gW+1 end end;function gR(g_)local an={}for dc=1,#g_,3 do local h0,h1,h2,h3=I(u(g_,dc,dc+2)..'\0',1,-1)an[#an+1]=gV[f(h0/4)]..gV[h0%4*16+f(h1/16)]..gV[h2 and h1%16*4+f(h2/64)or-1]..gV[h3 and h2%64 or-1]end;return bO(an)end;function gS(h4)local an,h5={},3;for dc,gZ in bR(bQ(h4,'%s+',''),'()(.)')do local h6=gV[gZ]if h6<0 then h5=h5-1;h6=0 end;local ct=dc%4;if ct>0 then an[-ct]=h6 else local h0=an[-1]*4+f(an[-2]/16)local h1=an[-2]%16*16+f(an[-3]/4)local h2=an[-3]%4*64+h6;an[#an+1]=u(ak(h0,h1,h2),1,h5)end end;return bO(an)end end;local h7;local function h8(d8,g3,h9)return bQ(d8,".",function(dd)return ak(cq(I(dd),h9))end)..bP(ak(h9),g3-#d8)end;local function ha(hb,aU,gn)local hc=h7[hb]if not hc then error("Unknown hash function",2)end;if#aU>hc then aU=gQ(hb(aU))end;local hd=hb()(h8(aU,hc,0x36))local an;local function gq(gr)if not gr then an=an or hb(h8(aU,hc,0x5C)..gQ(hd()))return an elseif an then error("Adding more chunks is not allowed after receiving the result",2)else hd(gr)return gq end end;if gn then return gq(gn)()else return gq end end;local he={md5=gw,sha1=gy,sha224=function(gn)return gm(224,gn)end,sha256=function(gn)return gm(256,gn)end,sha512_224=function(gn)return gv(224,gn)end,sha512_256=function(gn)return gv(256,gn)end,sha384=function(gn)return gv(384,gn)end,sha512=function(gn)return gv(512,gn)end,sha3_224=function(gn)return gz((1600-2*224)/8,224/8,false,gn)end,sha3_256=function(gn)return gz((1600-2*256)/8,256/8,false,gn)end,sha3_384=function(gn)return gz((1600-2*384)/8,384/8,false,gn)end,sha3_512=function(gn)return gz((1600-2*512)/8,512/8,false,gn)end,shake128=function(gA,gn)return gz((1600-2*128)/8,gA,true,gn)end,shake256=function(gA,gn)return gz((1600-2*256)/8,gA,true,gn)end,hmac=ha,hex2bin=gQ,base642bin=gS,bin2base64=gR}h7={[he.md5]=64,[he.sha1]=64,[he.sha224]=64,[he.sha256]=64,[he.sha512_224]=128,[he.sha512_256]=128,[he.sha384]=128,[he.sha512]=128,[he.sha3_224]=(1600-2*224)/8,[he.sha3_256]=(1600-2*256)/8,[he.sha3_384]=(1600-2*384)/8,[he.sha3_512]=(1600-2*512)/8}return he end)()local hf=require("cc.expect").expect;local hg=bM.sha256;local function hh(hi,hj)local aZ={}local a_={}local b0={}for B=1,#hi do aZ[#aZ+1]=string.byte(hi,B)end;for B=1,#hj do a_[#a_+1]=string.byte(hj,B)end;for B=1,#aZ do b0[#b0+1]=string.char(bit32.bxor(aZ[B],a_[B]))end;return table.concat(b0)end;local function gQ(d8)return d8:gsub("%x%x",function(bp)return string.char(tonumber(bp,16))end)end;local function hk(hl,hm,hn,ho)local b3;local b2;b3=gQ(bM.hmac(hl,hm,hn.."\1"))b2=b3;for B=2,ho do b3=gQ(bM.hmac(hl,hm,b3))b2=hh(b2,b3)end;return b2 end;local function hp(ab)local hq=""for cc,b4 in ipairs(ab)do hq=hq..string.char(b4)end;return hq end;local aU,hn,hr;local hs=fs;_G.fs={getName=hs.getName,getDrive=hs.getDrive,getFreeSpace=hs.getFreeSpace,combine=hs.combine,getDir=hs.getDir,isDriveRoot=hs.isDriveRoot,getCapacity=hs.getCapacity}function fs.unlock(bD)math.randomseed(os.epoch("utc"))if not bD then write("Please enter the password: ")bD=read("\7")end;local ab;hn=""if hs.exists("f1a36aae5f891a6c695d12621d1e0ecc4cee1a5e951784d874b8e6ad94de223f")then local ht=hs.open("f1a36aae5f891a6c695d12621d1e0ecc4cee1a5e951784d874b8e6ad94de223f","rb")local b2=ht.readAll()ht.close()hn,ab=b2:sub(1,16),{b2:sub(17):byte(1,16)}else for cc=1,16 do hn=hn..string.char(math.random(0,255))end end;aU=hk(hg,bD,hn,2500)bD=nil;hr={}if hs.exists("9f721fc36d10270affc7dbba9594e7665f95e0ad6d1729f5d9c0e6cc18235cf3")then local ht=hs.open("9f721fc36d10270affc7dbba9594e7665f95e0ad6d1729f5d9c0e6cc18235cf3","rb")local d8=b.decrypt(aU,ht.readAll(),32,b.CBCMODE,ab,true)ht.close()if d8==nil then aU,hn,hr=nil;error("Incorrect password.",2)end;hr=textutils.unserialize(d8)end end;local function hu()if aU==nil or hr==nil then return end;local ab={}if hs.exists("f1a36aae5f891a6c695d12621d1e0ecc4cee1a5e951784d874b8e6ad94de223f")then local ht=hs.open("f1a36aae5f891a6c695d12621d1e0ecc4cee1a5e951784d874b8e6ad94de223f","rb")local b2=ht.readAll()ht.close()ab={b2:sub(17):byte(1,16)}else for B=1,16 do ab[B]=math.random(0,255)end;local ht=hs.open("f1a36aae5f891a6c695d12621d1e0ecc4cee1a5e951784d874b8e6ad94de223f","wb")ht.write(hn..hp(ab))ht.close()end;local ht=hs.open("9f721fc36d10270affc7dbba9594e7665f95e0ad6d1729f5d9c0e6cc18235cf3","wb")ht.write(b.encrypt(aU,textutils.serialize(hr),32,b.CBCMODE,ab,true))ht.close()end;function fs.isUnlocked()return aU~=nil and hn~=nil and hr~=nil end;function fs.lock()hu()aU,hn,hr=nil end;local function hv(g8)local hq={}for bZ in g8:gmatch("[^/]+")do table.insert(hq,bZ)end;return hq end;local function hw(hx,b2)if#hx==0 then return b2 elseif type(b2)~="table"then return nil else local B=table.remove(hx,1)return hw(hx,b2[B])end end;local function hy(hz)return hw(hv(hz),hr)end;local function hA(hx,b4,b2)if#hx>1 and b2[hx[1]]==nil then b2[hx[1]]={}end;if#hx==0 then error("Critical error while writing encrypted data")elseif#hx==1 then b2[hx[1]]=b4 else return hA(hx,b4,b2[table.remove(hx,1)])end end;local function hB(hz,b4)return hA(hv(hz),b4,hr)end;local hC="^%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x$"local function hD(hz)return fs.combine(hz,""):match(hC)~=nil or fs.combine(hz,"")==".salt"or fs.combine(hz,"")==".filetree"end;function fs.list(hE)hf(1,hE,"string")local hF,hq=pcall(hs.list,hE)local hG=hy(hE)if not hF and type(hG)~="table"then error(hq:gsub("^.-:%d: ",""),2)end;hq=hF and hq or{}if type(hG)=="table"then for bY in pairs(hG)do table.insert(hq,bY)end end;if fs.combine(hE,"")==""then local hH={}for cc,b4 in ipairs(hq)do if not hD(b4)then table.insert(hH,b4)end end;hq=hH end;table.sort(hq)return hq end;function fs.exists(hz)hf(1,hz,"string")if hD(hz)then return false else return hs.exists(hz)or hy(hz)~=nil end end;function fs.isDir(hz)hf(1,hz,"string")if hD(hz)then return false else return hs.isDir(hz)or type(hy(hz))=="table"end end;function fs.isReadOnly(hz)hf(1,hz,"string")return hs.isReadOnly(hz)end;function fs.getSize(hz)hf(1,hz,"string")if hD(hz)then error("/"..fs.combine(hz,"")..": No such file",2)end;local hF,hq=pcall(hs.getSize,hz)local hG=hy(hz)if not hF and hG==nil then error(hq:gsub("^.-:%d: ",""),2)elseif type(hG)=="table"then return 0 elseif hF then return hq end;local ht=fs.open(hz,"rb")hq=#ht.readAll()ht.close()return hq end;function fs.makeDir(hz)hf(1,hz,"string")if hD(hz)then error("/"..fs.combine(hz,"")..": File exists",2)elseif hr==nil then return hs.makeDir(hz)elseif type(hy(hz))=="string"then error("/"..fs.combine(hz,"")..": File exists",2)end;hB(hz,hy(hz)or{})hu()end;function fs.move(hI,hJ)hf(1,hI,"string")hf(2,hJ,"string")if hD(hI)then error("/"..fs.combine(hI,"")..": No such file or directory",2)elseif hD(hJ)then error("/"..fs.combine(hJ,"")..": Permission denied",2)elseif hs.exists(hI)or hr==nil then return hs.move(hI,hJ)elseif hy(hI)==nil then error("/"..fs.combine(hI,"")..": No such file or directory",2)elseif hy(hJ)~=nil then error("/"..fs.combine(hJ,"")..": File exists",2)end;hB(hJ,hy(hI))hB(hI,nil)hu()end;function fs.copy(hI,hJ)hf(1,hI,"string")hf(2,hJ,"string")if hD(hI)then error("/"..fs.combine(hI,"")..": No such file or directory",2)elseif hD(hJ)then error("/"..fs.combine(hJ,"")..": Permission denied",2)elseif hs.exists(hI)or hr==nil then return hs.copy(hI,hJ)elseif hy(hI)==nil then error("/"..fs.combine(hI,"")..": No such file or directory",2)elseif hy(hJ)~=nil then error("/"..fs.combine(hJ,"")..": File exists",2)end;hB(hJ,hy(hI))hu()end;function fs.delete(hz)hf(1,hz,"string")if hD(hz)then error("/"..fs.combine(hz,"")..": Permission denied",2)elseif hs.exists(hz)or hr==nil then return hs.delete(hz)end;hB(hz,nil)hu()end;function fs.open(hz,bI)hf(1,hz,"string")hf(2,bI,"string")if hD(hz)then return nil,"/"..fs.combine(hz,"")..(bI:sub(1,1)~="w"and": No such file"or": Permission denied")elseif hs.exists(hz)or hr==nil then return hs.open(hz,bI)elseif({r=1,w=1,a=1,rb=1,wb=1,ab=1})[bI]==nil then return nil,"/"..fs.combine(hz,"")..": Unknown mode"end;local hK,dc="",1;local hL=bI:sub(2,2)=="b"local hM=false;if bI:sub(1,1)~="w"then local ab=hy(hz)if type(ab)~="string"then return nil,"/"..fs.combine(hz,"")..(ab==nil and": No such file"or": Is a directory")end;local ht,hN=hs.open(hg(fs.combine(hz,"")..ab),"rb")if not ht then return ht,hN end;hK=b.decrypt(aU,ht.readAll(),32,b.CBCMODE,{ab:byte(1,16)},true)ht.close()if hK==nil then return nil,"Failed to decrypt file"end;if not hL then local d8=""for cc,b4 in utf8.codes(hK)do if b4<256 then d8=d8 ..string.char(b4)else d8=d8 .."?"end end;hK=d8 end end;if bI:sub(1,1)=="a"then dc=#hK+1 end;if bI:sub(1,1)=="r"then return{read=function(m)hf(1,m,"number","nil")if dc>#hK then return nil elseif hM then error("attempt to use a closed file",2)elseif m==nil then dc=dc+1;if hL then return hK:byte(dc-1)else return hK:sub(dc-1,dc-1)end else dc=dc+m;return hK:sub(dc-m,dc-1)end end,readLine=function()if dc>#hK then return nil elseif hM then error("attempt to use a closed file",2)end;local hq=""for dd in hK:sub(dc):gmatch(".")do dc=dc+1;if dd=='\n'then break end;hq=hq..dd end;return hq end,readAll=function()if dc>#hK then return nil elseif hM then error("attempt to use a closed file",2)end;local hq=hK:sub(dc)dc=#hK+1;return hq end,seek=hL and function(hO,bx)hf(1,hO,"string","nil")hf(2,bx,"number","nil")if hM then error("attempt to use a closed file",2)end;hO=hO or"cur"bx=bx or 0;if hO=="set"then dc=bx+1 elseif hO=="cur"then dc=dc+bx elseif hO=="end"then dc=#hK-bx+1 else error("bad argument #1 to 'seek' (invalid option '"..hO.."')")end;return dc-1 end or nil,close=function()if hM then error("attempt to use a closed file",2)end;hM=true;dc=#hK+1 end}else return{write=function(_)hf(1,_,"string","number")if hM then error("attempt to use a closed file",2)end;if type(_)=="number"then if hL then _=string.char(_)or'?'else _=tostring(_)end end;hK=hK:sub(1,dc-1).._..hK:sub(dc+#_)end,writeLine=function(_)hf(1,_,"string","number")if hM then error("attempt to use a closed file",2)end;if type(_)=="number"then if hL then _=string.char(_)or'?'else _=tostring(_)end end;_=_.."\n"hK=hK:sub(1,dc-1).._..hK:sub(dc+#_)end,flush=function()if hM then error("attempt to use a closed file",2)end;local _=""if not hL then for dd in hK:gmatch(".")do _=_..utf8.char(dd:byte())end else _=hK end;local ab=hy(hz)if ab then ab={ab:byte(1,16)}else ab={}for B=1,16 do ab[B]=math.random(0,255)end end;local ht=hs.open(hg(fs.combine(hz,"")..hp(ab)),"wb")ht.write(b.encrypt(aU,_,32,b.CBCMODE,ab,true))ht.close()hB(hz,hp(ab))hu()end,seek=hL and function(hO,bx)if hM then error("attempt to use a closed file",2)end;hO=hO or"cur"bx=bx or 0;if hO=="set"then dc=bx+1 elseif hO=="cur"then dc=dc+bx elseif hO=="end"then dc=#hK-bx+1 else error("bad argument #1 to 'seek' (invalid option '"..hO.."')")end;return dc-1 end or nil,close=function()if hM then error("attempt to use a closed file",2)end;local _=""if not hL then for dd in hK:gmatch(".")do _=_..utf8.char(dd:byte())end else _=hK end;local ab=hy(hz)if ab then ab={ab:byte(1,16)}else ab={}for B=1,16 do ab[B]=math.random(0,255)end end;local ht=hs.open(hg(fs.combine(hz,"")..hp(ab)),"wb")ht.write(b.encrypt(aU,_,32,b.CBCMODE,ab,true))ht.close()hB(hz,hp(ab))hu()hM=true;dc=#hK+1 end}end end;local function hP(gH,b2)b2=b2 or hr;if#gH==0 then return b2 elseif type(b2)~="table"then return nil end;local hQ={}for B,b4 in ipairs(gH)do hQ[B]=b4 end;local hR=table.remove(hQ,1)local hq={}for bY,b4 in pairs(b2)do if bY:match("^"..hR:gsub("([%%%.])","%%%1"):gsub("%*","%.%*").."$")then hq[bY]=hP(hQ,b4)end end;return hq end;local function hS(b2,a4)a4=a4 or""if b2==nil then return{}end;local hq={}for bY,b4 in pairs(b2)do if type(b4)=="string"then table.insert(hq,a4 ..bY)else for cc,b5 in ipairs(hS(b4,a4 ..bY.."/"))do table.insert(hq,b5)end end end;return hq end;function fs.find(hT)hf(1,hT,"string")local hq=hs.find(hT)for cc,b4 in ipairs(hS(hP(hv(hT))))do table.insert(hq,b4)end;local hH={}for cc,b4 in ipairs(hq)do if not hD(fs.getName(b4))then table.insert(hH,b4)end end;hq=hH;table.sort(hq)return hq end;function fs.attributes(hz)hf(1,hz,"string")if hs.exists(hz)or hr==nil then return hs.attributes(hz)end;local _=hy(hz)local hU;if _==nil then error("/"..fs.combine(hz,"")..": No such file",2)elseif type(_)=="table"then hU=hs.attributes("9f721fc36d10270affc7dbba9594e7665f95e0ad6d1729f5d9c0e6cc18235cf3")hU.isDir=true;hU.size=0 else hU=hs.attributes(hg(fs.combine(hz,"").._))hU.isDir=false;hU.size=fs.getSize(hz)end;return hU end;local hV={}function fs.complete(hW,hX,hY,hZ)if type(hW)~="string"then error("bad argument #1 (expected string, got "..type(hW)..")",2)end;if type(hX)~="string"then error("bad argument #2 (expected string, got "..type(hX)..")",2)end;if hY~=nil and type(hY)~="boolean"then error("bad argument #3 (expected boolean, got "..type(hY)..")",2)end;if hZ~=nil and type(hZ)~="boolean"then error("bad argument #4 (expected boolean, got "..type(hZ)..")",2)end;hY=hY~=false;hZ=hZ~=false;local h_=hX;local i0=1;local i1=string.find(hW,"[/\\]",i0)if i1==1 then h_=""i0=2 end;local i2;while not i2 do local i1=string.find(hW,"[/\\]",i0)if i1 then local i3=string.sub(hW,i0,i1-1)h_=fs.combine(h_,i3)i0=i1+1 else i2=string.sub(hW,i0)end end;if fs.isDir(h_)then local i4={}if hZ and hW==""then table.insert(i4,".")end;if h_~=""then if hW==""then table.insert(i4,hZ and".."or"../")elseif hW=="."then table.insert(i4,hZ and"."or"./")end end;local i5=fs.list(h_)for m=1,#i5 do local i6=i5[m]if#i6>=#i2 and string.sub(i6,1,#i2)==i2 then local i7=fs.isDir(fs.combine(h_,i6))local i8=string.sub(i6,#i2+1)if i7 then table.insert(i4,i8 .."/")if hZ and#i8>0 then table.insert(i4,i8)end else if hY and#i8>0 then table.insert(i4,i8)end end end end;return i4 end;return hV end;function fs.encrypt(hI,hJ)hf(1,hI,"string")hf(2,hJ,"string")if hr==nil then error("Cannot encrypt files while locked",2)elseif not hs.exists(hI)then error("/"..fs.combine(hI,"")..": No such file",2)elseif hs.isDir(hI)then error("/"..fs.combine(hI,"")..": Is a directory",2)elseif hy(hJ)~=nil then error("/"..fs.combine(hJ,"")..": File exists",2)end;local ab={}for B=1,16 do ab[B]=math.random(0,255)end;local i9=hs.open(hI,"rb")local ia=hs.open(hg(fs.combine(hJ,"")..hp(ab)),"wb")ia.write(b.encrypt(aU,i9.readAll(),32,b.CBCMODE,ab,true))i9.close()ia.close()hB(hJ,hp(ab))hu()end;function fs.decrypt(hI,hJ)hf(1,hI,"string")hf(2,hJ,"string")local ab=hy(hI)if hr==nil then error("Cannot decrypt files while locked",2)elseif ab==nil then error("/"..fs.combine(hI,"")..": No such file",2)elseif type(ab)=="table"then error("/"..fs.combine(hI,"")..": Is a directory",2)elseif hs.exists(hJ)then error("/"..fs.combine(hJ,"")..": File exists",2)end;local i9=hs.open(hg(fs.combine(hI,"")..ab),"rb")local ia=hs.open(hJ,"wb")ia.write(b.decrypt(aU,i9.readAll(),32,b.CBCMODE,{ab:byte(1,16)},true))i9.close()ia.close()end;_G.io={}do local ib=_G.type;local function ic(id,...)if...==nil and id._autoclose and not id._closed then id:close()end;return...end;local ie;ie={__name="FILE*",__tostring=function(self)if self._closed then return"file (closed)"else local ig=tostring(self._handle):match("table: (%x+)")return"file ("..ig..")"end end,__index={close=function(self)if ib(self)~="table"or getmetatable(self)~=ie then error("bad argument #1 (FILE expected, got "..ib(self)..")",2)end;if self._closed then error("attempt to use a closed file",2)end;local id=self._handle;if id.close then self._closed=true;id.close()return true else return nil,"attempt to close standard stream"end end,flush=function(self)if ib(self)~="table"or getmetatable(self)~=ie then error("bad argument #1 (FILE expected, got "..ib(self)..")",2)end;if self._closed then error("attempt to use a closed file",2)end;local id=self._handle;if id.flush then id.flush()end;return true end,lines=function(self,...)if ib(self)~="table"or getmetatable(self)~=ie then error("bad argument #1 (FILE expected, got "..ib(self)..")",2)end;if self._closed then error("attempt to use a closed file",2)end;local id=self._handle;if not id.read then return nil,"file is not readable"end;local a=table.pack(...)return function()if self._closed then error("file is already closed",2)end;return ic(self,self:read(table.unpack(a,1,a.n)))end end,read=function(self,...)if ib(self)~="table"or getmetatable(self)~=ie then error("bad argument #1 (FILE expected, got "..ib(self)..")",2)end;if self._closed then error("attempt to use a closed file",2)end;local id=self._handle;if not id.read and not id.readLine then return nil,"Not opened for reading"end;local m=select("#",...)local S={}for B=1,m do local ih=select(B,...)local cB;if ib(ih)=="number"then if id.read then cB=id.read(ih)end elseif ib(ih)=="string"then local ii=ih:gsub("^%*",""):sub(1,1)if ii=="l"then if id.readLine then cB=id.readLine()end elseif ii=="L"and id.readLine then if id.readLine then cB=id.readLine(true)end elseif ii=="a"then if id.readAll then cB=id.readAll()or""end elseif ii=="n"then cB=nil else error("bad argument #"..B.." (invalid format)",2)end else error("bad argument #"..B.." (expected string, got "..ib(ih)..")",2)end;S[B]=cB;if not cB then break end end;if m==0 and id.readLine then return id.readLine()end;return table.unpack(S,1,m)end,seek=function(self,hO,bx)if ib(self)~="table"or getmetatable(self)~=ie then error("bad argument #1 (FILE expected, got "..ib(self)..")",2)end;if self._closed then error("attempt to use a closed file",2)end;local id=self._handle;if not id.seek then return nil,"file is not seekable"end;return id.seek(hO,bx)end,setvbuf=function(self,bI,d5)end,write=function(self,...)if ib(self)~="table"or getmetatable(self)~=ie then error("bad argument #1 (FILE expected, got "..ib(self)..")",2)end;if self._closed then error("attempt to use a closed file",2)end;local id=self._handle;if not id.write then return nil,"file is not writable"end;for B=1,select("#",...)do local ih=select(B,...)hf(B,ih,"string","number")id.write(ih)end;return self end}}local ij=setmetatable({_handle={readLine=_G.read}},ie)local ik=setmetatable({_handle={write=_G.write}},ie)local il=setmetatable({_handle={write=function(...)local im;if term.isColour()then im=term.getTextColour()term.setTextColour(colors.red)end;_G.write(...)if term.isColour()then term.setTextColour(im)end end}},ie)local ip=ij;local iq=ik;io.stdin=ij;io.stdout=ik;io.stderr=il;function io.close(ht)if ht==nil then return iq:close()end;if ib(ht)~="table"or getmetatable(ht)~=ie then error("bad argument #1 (FILE expected, got "..ib(ht)..")",2)end;return ht:close()end;function io.flush()return iq:flush()end;function io.input(ht)if ib(ht)=="string"then local cB,hN=open(ht,"rb")if not cB then error(hN,2)end;ip=cB elseif ib(ht)=="table"and getmetatable(ht)==ie then ip=ht elseif ht~=nil then error("bad fileument #1 (FILE expected, got "..ib(ht)..")",2)end;return ip end;function io.lines(ir,...)hf(1,ir,"string","nil")if ir then local hF,hN=open(ir,"rb")if not hF then error(hN,2)end;hF._autoclose=true;return hF:lines(...)else return ip:lines(...)end end;function io.open(ir,bI)hf(1,ir,"string")hf(2,bI,"string","nil")local is=bI and bI:gsub("%+","")or"rb"local ht,hN=fs.open(ir,is)if not ht then return nil,hN end;return setmetatable({_handle=ht},ie)end;function io.output(ht)if ib(ht)=="string"then local cB,hN=open(ht,"wb")if not cB then error(hN,2)end;iq=cB elseif ib(ht)=="table"and getmetatable(ht)==ie then iq=ht elseif ht~=nil then error("bad argument #1 (FILE expected, got "..ib(ht)..")",2)end;return iq end;function io.read(...)return ip:read(...)end;function io.type(it)if ib(it)=="table"and getmetatable(it)==ie then if it._closed then return"closed file"else return"file"end end;return nil end;function io.write(...)return iq:write(...)end end;if debug then local iu,iv=debug.getupvalue,debug.setupvalue;local iw,ix;function iw(iy,iz)if iy==iw then return nil end;for cc,b4 in pairs(fs)do if iy==b4 then return nil end end;return iu(iy,iz)end;function ix(iy,iz,iA)if iy==ix then return nil end;for cc,b4 in pairs(fs)do if iy==b4 then return nil end end;return iv(iy,iz,iA)end;debug.getupvalue=iw;debug.setupvalue=ix end;fs.unlock()print("FSEncrypt is now loaded.\nThe filesystem is now unlocked.") |
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
-------------------------------------------------------------------------------------------------------------------------- | |
-- sha2.lua | |
-------------------------------------------------------------------------------------------------------------------------- | |
-- VERSION: 9 (2020-05-10) | |
-- AUTHOR: Egor Skriptunoff | |
-- LICENSE: MIT (the same license as Lua itself) | |
-- | |
-- | |
-- DESCRIPTION: | |
-- This module contains functions to calculate SHA digest: | |
-- MD5, SHA-1, | |
-- SHA-224, SHA-256, SHA-512/224, SHA-512/256, SHA-384, SHA-512, | |
-- SHA3-224, SHA3-256, SHA3-384, SHA3-512, SHAKE128, SHAKE256, | |
-- HMAC | |
-- Written in pure Lua. | |
-- Compatible with: | |
-- Lua 5.1, Lua 5.2, Lua 5.3, Lua 5.4, Fengari, LuaJIT 2.0/2.1 (any CPU endianness). | |
-- Main feature of this module: it was heavily optimized for speed. | |
-- For every Lua version the module contains particular implementation branch to get benefits from version-specific features. | |
-- - branch for Lua 5.1 (emulating bitwise operators using look-up table) | |
-- - branch for Lua 5.2 (using bit32/bit library), suitable for both Lua 5.2 with native "bit32" and Lua 5.1 with external library "bit" | |
-- - branch for Lua 5.3/5.4 (using native 64-bit bitwise operators) | |
-- - branch for Lua 5.3/5.4 (using native 32-bit bitwise operators) for Lua built with LUA_INT_TYPE=LUA_INT_INT | |
-- - branch for LuaJIT without FFI library (useful in a sandboxed environment) | |
-- - branch for LuaJIT x86 without FFI library (LuaJIT x86 has oddity because of lack of CPU registers) | |
-- - branch for LuaJIT 2.0 with FFI library (bit.* functions work only with Lua numbers) | |
-- - branch for LuaJIT 2.1 with FFI library (bit.* functions can work with "int64_t" arguments) | |
-- | |
-- | |
-- USAGE: | |
-- Input data should be provided as a binary string: either as a whole string or as a sequence of substrings (chunk-by-chunk loading, total length < 9*10^15 bytes). | |
-- Result (SHA digest) is returned in hexadecimal representation as a string of lowercase hex digits. | |
-- Simplest usage example: | |
-- local sha = require("sha2") | |
-- local your_hash = sha.sha256("your string") | |
-- See file "sha2_test.lua" for more examples. | |
-- | |
-- | |
-- CHANGELOG: | |
-- version date description | |
-- ------- ---------- ----------- | |
-- 9 2020-05-10 Now works in OpenWrt's Lua (dialect of Lua 5.1 with "double" + "invisible int32") | |
-- 8 2019-09-03 SHA3 functions added | |
-- 7 2019-03-17 Added functions to convert to/from base64 | |
-- 6 2018-11-12 HMAC added | |
-- 5 2018-11-10 SHA-1 added | |
-- 4 2018-11-03 MD5 added | |
-- 3 2018-11-02 Bug fixed: incorrect hashing of long (2 GByte) data streams on Lua 5.3/5.4 built with "int32" integers | |
-- 2 2018-10-07 Decreased module loading time in Lua 5.1 implementation branch (thanks to Peter Melnichenko for giving a hint) | |
-- 1 2018-10-06 First release (only SHA-2 functions) | |
----------------------------------------------------------------------------- | |
local print_debug_messages = false -- set to true to view some messages about your system's abilities and implementation branch chosen for your system | |
local unpack, table_concat, byte, char, string_rep, sub, gsub, gmatch, string_format, floor, ceil, math_min, math_max, tonumber, type = | |
table.unpack or unpack, table.concat, string.byte, string.char, string.rep, string.sub, string.gsub, string.gmatch, string.format, math.floor, math.ceil, math.min, math.max, tonumber, type | |
-------------------------------------------------------------------------------- | |
-- EXAMINING YOUR SYSTEM | |
-------------------------------------------------------------------------------- | |
local function get_precision(one) | |
-- "one" must be either float 1.0 or integer 1 | |
-- returns bits_precision, is_integer | |
-- This function works correctly with all floating point datatypes (including non-IEEE-754) | |
local k, n, m, prev_n = 0, one, one | |
while true do | |
k, prev_n, n, m = k + 1, n, n + n + 1, m + m + k % 2 | |
if k > 256 or n - (n - 1) ~= 1 or m - (m - 1) ~= 1 or n == m then | |
return k, false -- floating point datatype | |
elseif n == prev_n then | |
return k, true -- integer datatype | |
end | |
end | |
end | |
-- Make sure Lua has "double" numbers | |
local x = 2/3 | |
local Lua_has_double = x * 5 > 3 and x * 4 < 3 and get_precision(1.0) >= 53 | |
assert(Lua_has_double, "at least 53-bit floating point numbers are required") | |
-- Q: | |
-- SHA2 was designed for FPU-less machines. | |
-- So, why floating point numbers are needed for this module? | |
-- A: | |
-- 53-bit "double" numbers are useful to calculate "magic numbers" used in SHA. | |
-- I prefer to write 50 LOC "magic numbers calculator" instead of storing more than 200 constants explicitly in this source file. | |
local int_prec, Lua_has_integers = get_precision(1) | |
local Lua_has_int64 = Lua_has_integers and int_prec == 64 | |
local Lua_has_int32 = Lua_has_integers and int_prec == 32 | |
assert(Lua_has_int64 or Lua_has_int32 or not Lua_has_integers, "Lua integers must be either 32-bit or 64-bit") | |
-- Q: | |
-- Does it mean that almost all non-standard configurations are not supported? | |
-- A: | |
-- Yes. Sorry, too many problems to support all possible Lua numbers configurations. | |
-- Lua 5.1/5.2 with "int32" will not work. | |
-- Lua 5.1/5.2 with "int64" will not work. | |
-- Lua 5.1/5.2 with "int128" will not work. | |
-- Lua 5.1/5.2 with "float" will not work. | |
-- Lua 5.1/5.2 with "double" is OK. (default config for Lua 5.1, Lua 5.2, LuaJIT) | |
-- Lua 5.3/5.4 with "int32" + "float" will not work. | |
-- Lua 5.3/5.4 with "int64" + "float" will not work. | |
-- Lua 5.3/5.4 with "int128" + "float" will not work. | |
-- Lua 5.3/5.4 with "int32" + "double" is OK. (config used by Fengari) | |
-- Lua 5.3/5.4 with "int64" + "double" is OK. (default config for Lua 5.3, Lua 5.4) | |
-- Lua 5.3/5.4 with "int128" + "double" will not work. | |
-- Using floating point numbers better than "double" instead of "double" is OK (non-IEEE-754 floating point implementation are allowed). | |
-- Using "int128" instead of "int64" is not OK: "int128" would require different branch of implementation for optimized SHA512. | |
-- Check for LuaJIT and 32-bit bitwise libraries | |
local is_LuaJIT = ({false, [1] = true})[1] and (type(jit) ~= "table" or jit.version_num >= 20000) -- LuaJIT 1.x.x is treated as vanilla Lua 5.1 | |
local is_LuaJIT_21 -- LuaJIT 2.1+ | |
local LuaJIT_arch | |
local ffi -- LuaJIT FFI library (as a table) | |
local b -- 32-bit bitwise library (as a table) | |
local library_name | |
if is_LuaJIT then | |
-- Assuming "bit" library is always available on LuaJIT | |
b = require"bit" | |
library_name = "bit" | |
-- "ffi" is intentionally disabled on some systems for safety reason | |
local LuaJIT_has_FFI, result = pcall(require, "ffi") | |
if LuaJIT_has_FFI then | |
ffi = result | |
end | |
is_LuaJIT_21 = not not loadstring"b=0b0" | |
LuaJIT_arch = type(jit) == "table" and jit.arch or ffi and ffi.arch or nil | |
else | |
-- For vanilla Lua, "bit"/"bit32" libraries are searched in global namespace only. No attempt is made to load a library if it's not loaded yet. | |
for _, libname in ipairs((_VERSION == "Lua 5.2" or type(_HOST) == "string") and {"bit32", "bit"} or {"bit", "bit32"}) do | |
if type(_G[libname]) == "table" and _G[libname].bxor then | |
b = _G[libname] | |
library_name = libname | |
break | |
end | |
end | |
end | |
-------------------------------------------------------------------------------- | |
-- You can disable here some of your system's abilities (for testing purposes) | |
-------------------------------------------------------------------------------- | |
-- is_LuaJIT = nil | |
-- is_LuaJIT_21 = nil | |
-- ffi = nil | |
-- Lua_has_int32 = nil | |
-- Lua_has_int64 = nil | |
-- b, library_name = nil | |
-------------------------------------------------------------------------------- | |
if print_debug_messages then | |
-- Printing list of abilities of your system | |
print("Abilities:") | |
print(" Lua version: "..(is_LuaJIT and "LuaJIT "..(is_LuaJIT_21 and "2.1 " or "2.0 ")..(LuaJIT_arch or "")..(ffi and " with FFI" or " without FFI") or _VERSION)) | |
print(" Integer bitwise operators: "..(Lua_has_int64 and "int64" or Lua_has_int32 and "int32" or "no")) | |
print(" 32-bit bitwise library: "..(library_name or "not found")) | |
end | |
-- Selecting the most suitable implementation for given set of abilities | |
local method, branch | |
if is_LuaJIT and ffi then | |
method = "Using 'ffi' library of LuaJIT" | |
branch = "FFI" | |
elseif is_LuaJIT then | |
method = "Using special code for FFI-less LuaJIT" | |
branch = "LJ" | |
elseif Lua_has_int64 then | |
method = "Using native int64 bitwise operators" | |
branch = "INT64" | |
elseif Lua_has_int32 then | |
method = "Using native int32 bitwise operators" | |
branch = "INT32" | |
elseif library_name then -- when bitwise library is available (Lua 5.2 with native library "bit32" or Lua 5.1 with external library "bit") | |
method = "Using '"..library_name.."' library" | |
branch = "LIB32" | |
else | |
method = "Emulating bitwise operators using look-up table" | |
branch = "EMUL" | |
end | |
if print_debug_messages then | |
-- Printing the implementation selected to be used on your system | |
print("Implementation selected:") | |
print(" "..method) | |
end | |
-------------------------------------------------------------------------------- | |
-- BASIC 32-BIT BITWISE FUNCTIONS | |
-------------------------------------------------------------------------------- | |
local AND, OR, XOR, SHL, SHR, ROL, ROR, NOT, NORM, HEX, XOR_BYTE | |
-- Only low 32 bits of function arguments matter, high bits are ignored | |
-- The result of all functions (except HEX) is an integer inside "correct range": | |
-- for "bit" library: (-2^31)..(2^31-1) | |
-- for "bit32" library: 0..(2^32-1) | |
if branch == "FFI" or branch == "LJ" or branch == "LIB32" then | |
-- Your system has 32-bit bitwise library (either "bit" or "bit32") | |
AND = b.band -- 2 arguments | |
OR = b.bor -- 2 arguments | |
XOR = b.bxor -- 2..5 arguments | |
SHL = b.lshift -- second argument is integer 0..31 | |
SHR = b.rshift -- second argument is integer 0..31 | |
ROL = b.rol or b.lrotate -- second argument is integer 0..31 | |
ROR = b.ror or b.rrotate -- second argument is integer 0..31 | |
NOT = b.bnot -- only for LuaJIT | |
NORM = b.tobit -- only for LuaJIT | |
HEX = b.tohex -- returns string of 8 lowercase hexadecimal digits | |
assert(AND and OR and XOR and SHL and SHR and ROL and ROR and NOT, "Library '"..library_name.."' is incomplete") | |
XOR_BYTE = XOR -- XOR of two bytes (0..255) | |
elseif branch == "EMUL" then | |
-- Emulating 32-bit bitwise operations using 53-bit floating point arithmetic | |
function SHL(x, n) | |
return (x * 2^n) % 2^32 | |
end | |
function SHR(x, n) | |
-- return (x % 2^32 - x % 2^n) / 2^n | |
x = x % 2^32 / 2^n | |
return x - x % 1 | |
end | |
function ROL(x, n) | |
x = x % 2^32 * 2^n | |
local r = x % 2^32 | |
return r + (x - r) / 2^32 | |
end | |
function ROR(x, n) | |
x = x % 2^32 / 2^n | |
local r = x % 1 | |
return r * 2^32 + (x - r) | |
end | |
local AND_of_two_bytes = {[0] = 0} -- look-up table (256*256 entries) | |
local idx = 0 | |
for y = 0, 127 * 256, 256 do | |
for x = y, y + 127 do | |
x = AND_of_two_bytes[x] * 2 | |
AND_of_two_bytes[idx] = x | |
AND_of_two_bytes[idx + 1] = x | |
AND_of_two_bytes[idx + 256] = x | |
AND_of_two_bytes[idx + 257] = x + 1 | |
idx = idx + 2 | |
end | |
idx = idx + 256 | |
end | |
local function and_or_xor(x, y, operation) | |
-- operation: nil = AND, 1 = OR, 2 = XOR | |
local x0 = x % 2^32 | |
local y0 = y % 2^32 | |
local rx = x0 % 256 | |
local ry = y0 % 256 | |
local res = AND_of_two_bytes[rx + ry * 256] | |
x = x0 - rx | |
y = (y0 - ry) / 256 | |
rx = x % 65536 | |
ry = y % 256 | |
res = res + AND_of_two_bytes[rx + ry] * 256 | |
x = (x - rx) / 256 | |
y = (y - ry) / 256 | |
rx = x % 65536 + y % 256 | |
res = res + AND_of_two_bytes[rx] * 65536 | |
res = res + AND_of_two_bytes[(x + y - rx) / 256] * 16777216 | |
if operation then | |
res = x0 + y0 - operation * res | |
end | |
return res | |
end | |
function AND(x, y) | |
return and_or_xor(x, y) | |
end | |
function OR(x, y) | |
return and_or_xor(x, y, 1) | |
end | |
function XOR(x, y, z, t, u) -- 2..5 arguments | |
if z then | |
if t then | |
if u then | |
t = and_or_xor(t, u, 2) | |
end | |
z = and_or_xor(z, t, 2) | |
end | |
y = and_or_xor(y, z, 2) | |
end | |
return and_or_xor(x, y, 2) | |
end | |
function XOR_BYTE(x, y) | |
return x + y - 2 * AND_of_two_bytes[x + y * 256] | |
end | |
end | |
HEX = HEX | |
or | |
pcall(string_format, "%x", 2^31) and | |
function (x) -- returns string of 8 lowercase hexadecimal digits | |
return string_format("%08x", x % 4294967296) | |
end | |
or | |
function (x) -- for OpenWrt's dialect of Lua | |
return string_format("%08x", (x + 2^31) % 2^32 - 2^31) | |
end | |
local function XOR32A5(x) | |
return XOR(x, 0xA5A5A5A5) % 4294967296 | |
end | |
local function create_array_of_lanes() | |
return {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} | |
end | |
-------------------------------------------------------------------------------- | |
-- CREATING OPTIMIZED INNER LOOP | |
-------------------------------------------------------------------------------- | |
-- Inner loop functions | |
local sha256_feed_64, sha512_feed_128, md5_feed_64, sha1_feed_64, keccak_feed | |
-- Arrays of SHA2 "magic numbers" (in "INT64" and "FFI" branches "*_lo" arrays contain 64-bit values) | |
local sha2_K_lo, sha2_K_hi, sha2_H_lo, sha2_H_hi, sha3_RC_lo, sha3_RC_hi = {}, {}, {}, {}, {}, {} | |
local sha2_H_ext256 = {[224] = {}, [256] = sha2_H_hi} | |
local sha2_H_ext512_lo, sha2_H_ext512_hi = {[384] = {}, [512] = sha2_H_lo}, {[384] = {}, [512] = sha2_H_hi} | |
local md5_K, md5_sha1_H = {}, {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0} | |
local md5_next_shift = {0, 0, 0, 0, 0, 0, 0, 0, 28, 25, 26, 27, 0, 0, 10, 9, 11, 12, 0, 15, 16, 17, 18, 0, 20, 22, 23, 21} | |
local HEX64, XOR64A5, lanes_index_base -- defined only for branches that internally use 64-bit integers: "INT64" and "FFI" | |
local common_W = {} -- temporary table shared between all calculations (to avoid creating new temporary table every time) | |
local K_lo_modulo, hi_factor, hi_factor_keccak = 4294967296, 0, 0 | |
local function build_keccak_format(elem) | |
local keccak_format = {} | |
for _, size in ipairs{1, 9, 13, 17, 18, 21} do | |
keccak_format[size] = "<"..string_rep(elem, size) | |
end | |
return keccak_format | |
end | |
if branch == "FFI" then | |
-- SHA256 implementation for "LuaJIT with FFI" branch | |
local common_W_FFI_int32 = ffi.new"int32_t[80]" -- 64 is enough for SHA256, but 80 is needed for SHA-1 | |
function sha256_feed_64(H, str, offs, size) | |
-- offs >= 0, size >= 0, size is multiple of 64 | |
local W, K = common_W_FFI_int32, sha2_K_hi | |
for pos = offs, offs + size - 1, 64 do | |
for j = 0, 15 do | |
pos = pos + 4 | |
local a, b, c, d = byte(str, pos - 3, pos) -- slow, but doesn't depend on endianness | |
W[j] = OR(SHL(a, 24), SHL(b, 16), SHL(c, 8), d) | |
end | |
for j = 16, 63 do | |
local a, b = W[j-15], W[j-2] | |
W[j] = NORM( XOR(ROR(a, 7), ROL(a, 14), SHR(a, 3)) + XOR(ROL(b, 15), ROL(b, 13), SHR(b, 10)) + W[j-7] + W[j-16] ) | |
end | |
local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8] | |
for j = 0, 63, 8 do -- Thanks to Peter Cawley for this workaround (unroll the loop to avoid "PHI shuffling too complex" due to PHIs overlap) | |
local z = NORM( XOR(g, AND(e, XOR(f, g))) + XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + (W[j] + K[j+1] + h) ) | |
h, g, f, e = g, f, e, NORM( d + z ) | |
d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z ) | |
z = NORM( XOR(g, AND(e, XOR(f, g))) + XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + (W[j+1] + K[j+2] + h) ) | |
h, g, f, e = g, f, e, NORM( d + z ) | |
d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z ) | |
z = NORM( XOR(g, AND(e, XOR(f, g))) + XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + (W[j+2] + K[j+3] + h) ) | |
h, g, f, e = g, f, e, NORM( d + z ) | |
d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z ) | |
z = NORM( XOR(g, AND(e, XOR(f, g))) + XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + (W[j+3] + K[j+4] + h) ) | |
h, g, f, e = g, f, e, NORM( d + z ) | |
d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z ) | |
z = NORM( XOR(g, AND(e, XOR(f, g))) + XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + (W[j+4] + K[j+5] + h) ) | |
h, g, f, e = g, f, e, NORM( d + z ) | |
d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z ) | |
z = NORM( XOR(g, AND(e, XOR(f, g))) + XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + (W[j+5] + K[j+6] + h) ) | |
h, g, f, e = g, f, e, NORM( d + z ) | |
d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z ) | |
z = NORM( XOR(g, AND(e, XOR(f, g))) + XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + (W[j+6] + K[j+7] + h) ) | |
h, g, f, e = g, f, e, NORM( d + z ) | |
d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z ) | |
z = NORM( XOR(g, AND(e, XOR(f, g))) + XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + (W[j+7] + K[j+8] + h) ) | |
h, g, f, e = g, f, e, NORM( d + z ) | |
d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z ) | |
end | |
H[1], H[2], H[3], H[4] = NORM(a + H[1]), NORM(b + H[2]), NORM(c + H[3]), NORM(d + H[4]) | |
H[5], H[6], H[7], H[8] = NORM(e + H[5]), NORM(f + H[6]), NORM(g + H[7]), NORM(h + H[8]) | |
end | |
end | |
local common_W_FFI_int64 = ffi.new"int64_t[80]" | |
local int64 = ffi.typeof"int64_t" | |
local int32 = ffi.typeof"int32_t" | |
local uint32 = ffi.typeof"uint32_t" | |
hi_factor = int64(2^32) | |
if is_LuaJIT_21 then -- LuaJIT 2.1 supports bitwise 64-bit operations | |
local AND64, OR64, XOR64, NOT64, SHL64, SHR64, ROL64, ROR64 -- introducing synonyms for better code readability | |
= AND, OR, XOR, NOT, SHL, SHR, ROL, ROR | |
HEX64 = HEX | |
-- SHA3 implementation for "LuaJIT 2.1 + FFI" branch | |
local lanes_arr64 = ffi.typeof"int64_t[30]" -- 25 + 5 for temporary usage | |
-- lanes array is indexed from 0 | |
lanes_index_base = 0 | |
hi_factor_keccak = int64(2^32) | |
function create_array_of_lanes() | |
return lanes_arr64() | |
end | |
function keccak_feed(lanes, _, str, offs, size, block_size_in_bytes) | |
-- offs >= 0, size >= 0, size is multiple of block_size_in_bytes, block_size_in_bytes is positive multiple of 8 | |
local RC = sha3_RC_lo | |
local qwords_qty = SHR(block_size_in_bytes, 3) | |
for pos = offs, offs + size - 1, block_size_in_bytes do | |
for j = 0, qwords_qty - 1 do | |
pos = pos + 8 | |
local h, g, f, e, d, c, b, a = byte(str, pos - 7, pos) -- slow, but doesn't depend on endianness | |
lanes[j] = XOR64(lanes[j], OR64(OR(SHL(a, 24), SHL(b, 16), SHL(c, 8), d) * int64(2^32), uint32(int32(OR(SHL(e, 24), SHL(f, 16), SHL(g, 8), h))))) | |
end | |
for round_idx = 1, 24 do | |
for j = 0, 4 do | |
lanes[25 + j] = XOR64(lanes[j], lanes[j+5], lanes[j+10], lanes[j+15], lanes[j+20]) | |
end | |
local D = XOR64(lanes[25], ROL64(lanes[27], 1)) | |
lanes[1], lanes[6], lanes[11], lanes[16] = ROL64(XOR64(D, lanes[6]), 44), ROL64(XOR64(D, lanes[16]), 45), ROL64(XOR64(D, lanes[1]), 1), ROL64(XOR64(D, lanes[11]), 10) | |
lanes[21] = ROL64(XOR64(D, lanes[21]), 2) | |
D = XOR64(lanes[26], ROL64(lanes[28], 1)) | |
lanes[2], lanes[7], lanes[12], lanes[22] = ROL64(XOR64(D, lanes[12]), 43), ROL64(XOR64(D, lanes[22]), 61), ROL64(XOR64(D, lanes[7]), 6), ROL64(XOR64(D, lanes[2]), 62) | |
lanes[17] = ROL64(XOR64(D, lanes[17]), 15) | |
D = XOR64(lanes[27], ROL64(lanes[29], 1)) | |
lanes[3], lanes[8], lanes[18], lanes[23] = ROL64(XOR64(D, lanes[18]), 21), ROL64(XOR64(D, lanes[3]), 28), ROL64(XOR64(D, lanes[23]), 56), ROL64(XOR64(D, lanes[8]), 55) | |
lanes[13] = ROL64(XOR64(D, lanes[13]), 25) | |
D = XOR64(lanes[28], ROL64(lanes[25], 1)) | |
lanes[4], lanes[14], lanes[19], lanes[24] = ROL64(XOR64(D, lanes[24]), 14), ROL64(XOR64(D, lanes[19]), 8), ROL64(XOR64(D, lanes[4]), 27), ROL64(XOR64(D, lanes[14]), 39) | |
lanes[9] = ROL64(XOR64(D, lanes[9]), 20) | |
D = XOR64(lanes[29], ROL64(lanes[26], 1)) | |
lanes[5], lanes[10], lanes[15], lanes[20] = ROL64(XOR64(D, lanes[10]), 3), ROL64(XOR64(D, lanes[20]), 18), ROL64(XOR64(D, lanes[5]), 36), ROL64(XOR64(D, lanes[15]), 41) | |
lanes[0] = XOR64(D, lanes[0]) | |
lanes[0], lanes[1], lanes[2], lanes[3], lanes[4] = XOR64(lanes[0], AND64(NOT64(lanes[1]), lanes[2]), RC[round_idx]), XOR64(lanes[1], AND64(NOT64(lanes[2]), lanes[3])), XOR64(lanes[2], AND64(NOT64(lanes[3]), lanes[4])), XOR64(lanes[3], AND64(NOT64(lanes[4]), lanes[0])), XOR64(lanes[4], AND64(NOT64(lanes[0]), lanes[1])) | |
lanes[5], lanes[6], lanes[7], lanes[8], lanes[9] = XOR64(lanes[8], AND64(NOT64(lanes[9]), lanes[5])), XOR64(lanes[9], AND64(NOT64(lanes[5]), lanes[6])), XOR64(lanes[5], AND64(NOT64(lanes[6]), lanes[7])), XOR64(lanes[6], AND64(NOT64(lanes[7]), lanes[8])), XOR64(lanes[7], AND64(NOT64(lanes[8]), lanes[9])) | |
lanes[10], lanes[11], lanes[12], lanes[13], lanes[14] = XOR64(lanes[11], AND64(NOT64(lanes[12]), lanes[13])), XOR64(lanes[12], AND64(NOT64(lanes[13]), lanes[14])), XOR64(lanes[13], AND64(NOT64(lanes[14]), lanes[10])), XOR64(lanes[14], AND64(NOT64(lanes[10]), lanes[11])), XOR64(lanes[10], AND64(NOT64(lanes[11]), lanes[12])) | |
lanes[15], lanes[16], lanes[17], lanes[18], lanes[19] = XOR64(lanes[19], AND64(NOT64(lanes[15]), lanes[16])), XOR64(lanes[15], AND64(NOT64(lanes[16]), lanes[17])), XOR64(lanes[16], AND64(NOT64(lanes[17]), lanes[18])), XOR64(lanes[17], AND64(NOT64(lanes[18]), lanes[19])), XOR64(lanes[18], AND64(NOT64(lanes[19]), lanes[15])) | |
lanes[20], lanes[21], lanes[22], lanes[23], lanes[24] = XOR64(lanes[22], AND64(NOT64(lanes[23]), lanes[24])), XOR64(lanes[23], AND64(NOT64(lanes[24]), lanes[20])), XOR64(lanes[24], AND64(NOT64(lanes[20]), lanes[21])), XOR64(lanes[20], AND64(NOT64(lanes[21]), lanes[22])), XOR64(lanes[21], AND64(NOT64(lanes[22]), lanes[23])) | |
end | |
end | |
end | |
-- SHA512 implementation for "LuaJIT 2.1 + FFI" branch | |
local A5_long = 0xA5A5A5A5 * int64(2^32 + 1) -- It's impossible to use constant 0xA5A5A5A5A5A5A5A5LL because it will raise syntax error on other Lua versions | |
function XOR64A5(long) | |
return XOR64(long, A5_long) | |
end | |
function sha512_feed_128(H, _, str, offs, size) | |
-- offs >= 0, size >= 0, size is multiple of 128 | |
local W, K = common_W_FFI_int64, sha2_K_lo | |
for pos = offs, offs + size - 1, 128 do | |
for j = 0, 15 do | |
pos = pos + 8 | |
local a, b, c, d, e, f, g, h = byte(str, pos - 7, pos) -- slow, but doesn't depend on endianness | |
W[j] = OR64(OR(SHL(a, 24), SHL(b, 16), SHL(c, 8), d) * int64(2^32), uint32(int32(OR(SHL(e, 24), SHL(f, 16), SHL(g, 8), h)))) | |
end | |
for j = 16, 79 do | |
local a, b = W[j-15], W[j-2] | |
W[j] = XOR64(ROR64(a, 1), ROR64(a, 8), SHR64(a, 7)) + XOR64(ROR64(b, 19), ROL64(b, 3), SHR64(b, 6)) + W[j-7] + W[j-16] | |
end | |
local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8] | |
for j = 0, 79, 8 do | |
local z = XOR64(ROR64(e, 14), ROR64(e, 18), ROL64(e, 23)) + XOR64(g, AND64(e, XOR64(f, g))) + h + K[j+1] + W[j] | |
h, g, f, e = g, f, e, z + d | |
d, c, b, a = c, b, a, XOR64(AND64(XOR64(a, b), c), AND64(a, b)) + XOR64(ROR64(a, 28), ROL64(a, 25), ROL64(a, 30)) + z | |
z = XOR64(ROR64(e, 14), ROR64(e, 18), ROL64(e, 23)) + XOR64(g, AND64(e, XOR64(f, g))) + h + K[j+2] + W[j+1] | |
h, g, f, e = g, f, e, z + d | |
d, c, b, a = c, b, a, XOR64(AND64(XOR64(a, b), c), AND64(a, b)) + XOR64(ROR64(a, 28), ROL64(a, 25), ROL64(a, 30)) + z | |
z = XOR64(ROR64(e, 14), ROR64(e, 18), ROL64(e, 23)) + XOR64(g, AND64(e, XOR64(f, g))) + h + K[j+3] + W[j+2] | |
h, g, f, e = g, f, e, z + d | |
d, c, b, a = c, b, a, XOR64(AND64(XOR64(a, b), c), AND64(a, b)) + XOR64(ROR64(a, 28), ROL64(a, 25), ROL64(a, 30)) + z | |
z = XOR64(ROR64(e, 14), ROR64(e, 18), ROL64(e, 23)) + XOR64(g, AND64(e, XOR64(f, g))) + h + K[j+4] + W[j+3] | |
h, g, f, e = g, f, e, z + d | |
d, c, b, a = c, b, a, XOR64(AND64(XOR64(a, b), c), AND64(a, b)) + XOR64(ROR64(a, 28), ROL64(a, 25), ROL64(a, 30)) + z | |
z = XOR64(ROR64(e, 14), ROR64(e, 18), ROL64(e, 23)) + XOR64(g, AND64(e, XOR64(f, g))) + h + K[j+5] + W[j+4] | |
h, g, f, e = g, f, e, z + d | |
d, c, b, a = c, b, a, XOR64(AND64(XOR64(a, b), c), AND64(a, b)) + XOR64(ROR64(a, 28), ROL64(a, 25), ROL64(a, 30)) + z | |
z = XOR64(ROR64(e, 14), ROR64(e, 18), ROL64(e, 23)) + XOR64(g, AND64(e, XOR64(f, g))) + h + K[j+6] + W[j+5] | |
h, g, f, e = g, f, e, z + d | |
d, c, b, a = c, b, a, XOR64(AND64(XOR64(a, b), c), AND64(a, b)) + XOR64(ROR64(a, 28), ROL64(a, 25), ROL64(a, 30)) + z | |
z = XOR64(ROR64(e, 14), ROR64(e, 18), ROL64(e, 23)) + XOR64(g, AND64(e, XOR64(f, g))) + h + K[j+7] + W[j+6] | |
h, g, f, e = g, f, e, z + d | |
d, c, b, a = c, b, a, XOR64(AND64(XOR64(a, b), c), AND64(a, b)) + XOR64(ROR64(a, 28), ROL64(a, 25), ROL64(a, 30)) + z | |
z = XOR64(ROR64(e, 14), ROR64(e, 18), ROL64(e, 23)) + XOR64(g, AND64(e, XOR64(f, g))) + h + K[j+8] + W[j+7] | |
h, g, f, e = g, f, e, z + d | |
d, c, b, a = c, b, a, XOR64(AND64(XOR64(a, b), c), AND64(a, b)) + XOR64(ROR64(a, 28), ROL64(a, 25), ROL64(a, 30)) + z | |
end | |
H[1] = a + H[1] | |
H[2] = b + H[2] | |
H[3] = c + H[3] | |
H[4] = d + H[4] | |
H[5] = e + H[5] | |
H[6] = f + H[6] | |
H[7] = g + H[7] | |
H[8] = h + H[8] | |
end | |
end | |
else -- LuaJIT 2.0 doesn't support 64-bit bitwise operations | |
-- SHA512 implementation for "LuaJIT 2.0 + FFI" branch | |
local union64 = ffi.typeof"union{int64_t i64; struct{int32_t lo, hi;} i32;}" | |
do -- make sure the struct is endianness-compatible | |
local u = union64(1) | |
if u.i32.lo < u.i32.hi then | |
union64 = ffi.typeof"union{int64_t i64; struct{int32_t hi, lo;} i32;}" | |
end | |
end | |
local unions64 = ffi.typeof("$[?]", union64) | |
local U = unions64(3) -- this array of unions is used for fast splitting int64 into int32_high and int32_low | |
-- "xorrific" 64-bit functions :-) | |
-- int64 input is splitted into two int32 parts, some bitwise 32-bit operations are performed, finally the result is converted to int64 | |
-- these functions are needed because bit.* functions in LuaJIT 2.0 don't work with int64_t | |
local function XORROR64_1(a) | |
-- return XOR64(ROR64(a, 1), ROR64(a, 8), SHR64(a, 7)) | |
U[0].i64 = a | |
local a_lo, a_hi = U[0].i32.lo, U[0].i32.hi | |
local t_lo = XOR(OR(SHR(a_lo, 1), SHL(a_hi, 31)), OR(SHR(a_lo, 8), SHL(a_hi, 24)), OR(SHR(a_lo, 7), SHL(a_hi, 25))) | |
local t_hi = XOR(OR(SHR(a_hi, 1), SHL(a_lo, 31)), OR(SHR(a_hi, 8), SHL(a_lo, 24)), SHR(a_hi, 7)) | |
return t_hi * int64(2^32) + uint32(int32(t_lo)) | |
end | |
local function XORROR64_2(b) | |
-- return XOR64(ROR64(b, 19), ROL64(b, 3), SHR64(b, 6)) | |
U[0].i64 = b | |
local b_lo, b_hi = U[0].i32.lo, U[0].i32.hi | |
local u_lo = XOR(OR(SHR(b_lo, 19), SHL(b_hi, 13)), OR(SHL(b_lo, 3), SHR(b_hi, 29)), OR(SHR(b_lo, 6), SHL(b_hi, 26))) | |
local u_hi = XOR(OR(SHR(b_hi, 19), SHL(b_lo, 13)), OR(SHL(b_hi, 3), SHR(b_lo, 29)), SHR(b_hi, 6)) | |
return u_hi * int64(2^32) + uint32(int32(u_lo)) | |
end | |
local function XORROR64_3(e) | |
-- return XOR64(ROR64(e, 14), ROR64(e, 18), ROL64(e, 23)) | |
U[0].i64 = e | |
local e_lo, e_hi = U[0].i32.lo, U[0].i32.hi | |
local u_lo = XOR(OR(SHR(e_lo, 14), SHL(e_hi, 18)), OR(SHR(e_lo, 18), SHL(e_hi, 14)), OR(SHL(e_lo, 23), SHR(e_hi, 9))) | |
local u_hi = XOR(OR(SHR(e_hi, 14), SHL(e_lo, 18)), OR(SHR(e_hi, 18), SHL(e_lo, 14)), OR(SHL(e_hi, 23), SHR(e_lo, 9))) | |
return u_hi * int64(2^32) + uint32(int32(u_lo)) | |
end | |
local function XORROR64_6(a) | |
-- return XOR64(ROR64(a, 28), ROL64(a, 25), ROL64(a, 30)) | |
U[0].i64 = a | |
local b_lo, b_hi = U[0].i32.lo, U[0].i32.hi | |
local u_lo = XOR(OR(SHR(b_lo, 28), SHL(b_hi, 4)), OR(SHL(b_lo, 30), SHR(b_hi, 2)), OR(SHL(b_lo, 25), SHR(b_hi, 7))) | |
local u_hi = XOR(OR(SHR(b_hi, 28), SHL(b_lo, 4)), OR(SHL(b_hi, 30), SHR(b_lo, 2)), OR(SHL(b_hi, 25), SHR(b_lo, 7))) | |
return u_hi * int64(2^32) + uint32(int32(u_lo)) | |
end | |
local function XORROR64_4(e, f, g) | |
-- return XOR64(g, AND64(e, XOR64(f, g))) | |
U[0].i64 = f | |
U[1].i64 = g | |
U[2].i64 = e | |
local f_lo, f_hi = U[0].i32.lo, U[0].i32.hi | |
local g_lo, g_hi = U[1].i32.lo, U[1].i32.hi | |
local e_lo, e_hi = U[2].i32.lo, U[2].i32.hi | |
local result_lo = XOR(g_lo, AND(e_lo, XOR(f_lo, g_lo))) | |
local result_hi = XOR(g_hi, AND(e_hi, XOR(f_hi, g_hi))) | |
return result_hi * int64(2^32) + uint32(int32(result_lo)) | |
end | |
local function XORROR64_5(a, b, c) | |
-- return XOR64(AND64(XOR64(a, b), c), AND64(a, b)) | |
U[0].i64 = a | |
U[1].i64 = b | |
U[2].i64 = c | |
local a_lo, a_hi = U[0].i32.lo, U[0].i32.hi | |
local b_lo, b_hi = U[1].i32.lo, U[1].i32.hi | |
local c_lo, c_hi = U[2].i32.lo, U[2].i32.hi | |
local result_lo = XOR(AND(XOR(a_lo, b_lo), c_lo), AND(a_lo, b_lo)) | |
local result_hi = XOR(AND(XOR(a_hi, b_hi), c_hi), AND(a_hi, b_hi)) | |
return result_hi * int64(2^32) + uint32(int32(result_lo)) | |
end | |
function XOR64A5(long) | |
-- return XOR64(long, 0xA5A5A5A5A5A5A5A5) | |
U[0].i64 = long | |
local lo32, hi32 = U[0].i32.lo, U[0].i32.hi | |
lo32 = XOR(lo32, 0xA5A5A5A5) | |
hi32 = XOR(hi32, 0xA5A5A5A5) | |
return hi32 * int64(2^32) + uint32(int32(lo32)) | |
end | |
function HEX64(long) | |
U[0].i64 = long | |
return HEX(U[0].i32.hi)..HEX(U[0].i32.lo) | |
end | |
function sha512_feed_128(H, _, str, offs, size) | |
-- offs >= 0, size >= 0, size is multiple of 128 | |
local W, K = common_W_FFI_int64, sha2_K_lo | |
for pos = offs, offs + size - 1, 128 do | |
for j = 0, 15 do | |
pos = pos + 8 | |
local a, b, c, d, e, f, g, h = byte(str, pos - 7, pos) -- slow, but doesn't depend on endianness | |
W[j] = OR(SHL(a, 24), SHL(b, 16), SHL(c, 8), d) * int64(2^32) + uint32(int32(OR(SHL(e, 24), SHL(f, 16), SHL(g, 8), h))) | |
end | |
for j = 16, 79 do | |
W[j] = XORROR64_1(W[j-15]) + XORROR64_2(W[j-2]) + W[j-7] + W[j-16] | |
end | |
local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8] | |
for j = 0, 79, 8 do | |
local z = XORROR64_3(e) + XORROR64_4(e, f, g) + h + K[j+1] + W[j] | |
h, g, f, e = g, f, e, z + d | |
d, c, b, a = c, b, a, XORROR64_5(a, b, c) + XORROR64_6(a) + z | |
z = XORROR64_3(e) + XORROR64_4(e, f, g) + h + K[j+2] + W[j+1] | |
h, g, f, e = g, f, e, z + d | |
d, c, b, a = c, b, a, XORROR64_5(a, b, c) + XORROR64_6(a) + z | |
z = XORROR64_3(e) + XORROR64_4(e, f, g) + h + K[j+3] + W[j+2] | |
h, g, f, e = g, f, e, z + d | |
d, c, b, a = c, b, a, XORROR64_5(a, b, c) + XORROR64_6(a) + z | |
z = XORROR64_3(e) + XORROR64_4(e, f, g) + h + K[j+4] + W[j+3] | |
h, g, f, e = g, f, e, z + d | |
d, c, b, a = c, b, a, XORROR64_5(a, b, c) + XORROR64_6(a) + z | |
z = XORROR64_3(e) + XORROR64_4(e, f, g) + h + K[j+5] + W[j+4] | |
h, g, f, e = g, f, e, z + d | |
d, c, b, a = c, b, a, XORROR64_5(a, b, c) + XORROR64_6(a) + z | |
z = XORROR64_3(e) + XORROR64_4(e, f, g) + h + K[j+6] + W[j+5] | |
h, g, f, e = g, f, e, z + d | |
d, c, b, a = c, b, a, XORROR64_5(a, b, c) + XORROR64_6(a) + z | |
z = XORROR64_3(e) + XORROR64_4(e, f, g) + h + K[j+7] + W[j+6] | |
h, g, f, e = g, f, e, z + d | |
d, c, b, a = c, b, a, XORROR64_5(a, b, c) + XORROR64_6(a) + z | |
z = XORROR64_3(e) + XORROR64_4(e, f, g) + h + K[j+8] + W[j+7] | |
h, g, f, e = g, f, e, z + d | |
d, c, b, a = c, b, a, XORROR64_5(a, b, c) + XORROR64_6(a) + z | |
end | |
H[1] = a + H[1] | |
H[2] = b + H[2] | |
H[3] = c + H[3] | |
H[4] = d + H[4] | |
H[5] = e + H[5] | |
H[6] = f + H[6] | |
H[7] = g + H[7] | |
H[8] = h + H[8] | |
end | |
end | |
end | |
-- MD5 implementation for "LuaJIT with FFI" branch | |
function md5_feed_64(H, str, offs, size) | |
-- offs >= 0, size >= 0, size is multiple of 64 | |
local W, K = common_W_FFI_int32, md5_K | |
for pos = offs, offs + size - 1, 64 do | |
for j = 0, 15 do | |
pos = pos + 4 | |
local a, b, c, d = byte(str, pos - 3, pos) -- slow, but doesn't depend on endianness | |
W[j] = OR(SHL(d, 24), SHL(c, 16), SHL(b, 8), a) | |
end | |
local a, b, c, d = H[1], H[2], H[3], H[4] | |
for j = 0, 15, 4 do | |
a, d, c, b = d, c, b, NORM(ROL(XOR(d, AND(b, XOR(c, d))) + (K[j+1] + W[j ] + a), 7) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(d, AND(b, XOR(c, d))) + (K[j+2] + W[j+1] + a), 12) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(d, AND(b, XOR(c, d))) + (K[j+3] + W[j+2] + a), 17) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(d, AND(b, XOR(c, d))) + (K[j+4] + W[j+3] + a), 22) + b) | |
end | |
for j = 16, 31, 4 do | |
local g = 5*j | |
a, d, c, b = d, c, b, NORM(ROL(XOR(c, AND(d, XOR(b, c))) + (K[j+1] + W[AND(g + 1, 15)] + a), 5) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(c, AND(d, XOR(b, c))) + (K[j+2] + W[AND(g + 6, 15)] + a), 9) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(c, AND(d, XOR(b, c))) + (K[j+3] + W[AND(g - 5, 15)] + a), 14) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(c, AND(d, XOR(b, c))) + (K[j+4] + W[AND(g , 15)] + a), 20) + b) | |
end | |
for j = 32, 47, 4 do | |
local g = 3*j | |
a, d, c, b = d, c, b, NORM(ROL(XOR(b, c, d) + (K[j+1] + W[AND(g + 5, 15)] + a), 4) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(b, c, d) + (K[j+2] + W[AND(g + 8, 15)] + a), 11) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(b, c, d) + (K[j+3] + W[AND(g - 5, 15)] + a), 16) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(b, c, d) + (K[j+4] + W[AND(g - 2, 15)] + a), 23) + b) | |
end | |
for j = 48, 63, 4 do | |
local g = 7*j | |
a, d, c, b = d, c, b, NORM(ROL(XOR(c, OR(b, NOT(d))) + (K[j+1] + W[AND(g , 15)] + a), 6) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(c, OR(b, NOT(d))) + (K[j+2] + W[AND(g + 7, 15)] + a), 10) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(c, OR(b, NOT(d))) + (K[j+3] + W[AND(g - 2, 15)] + a), 15) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(c, OR(b, NOT(d))) + (K[j+4] + W[AND(g + 5, 15)] + a), 21) + b) | |
end | |
H[1], H[2], H[3], H[4] = NORM(a + H[1]), NORM(b + H[2]), NORM(c + H[3]), NORM(d + H[4]) | |
end | |
end | |
-- SHA-1 implementation for "LuaJIT with FFI" branch | |
function sha1_feed_64(H, str, offs, size) | |
-- offs >= 0, size >= 0, size is multiple of 64 | |
local W = common_W_FFI_int32 | |
for pos = offs, offs + size - 1, 64 do | |
for j = 0, 15 do | |
pos = pos + 4 | |
local a, b, c, d = byte(str, pos - 3, pos) -- slow, but doesn't depend on endianness | |
W[j] = OR(SHL(a, 24), SHL(b, 16), SHL(c, 8), d) | |
end | |
for j = 16, 79 do | |
W[j] = ROL(XOR(W[j-3], W[j-8], W[j-14], W[j-16]), 1) | |
end | |
local a, b, c, d, e = H[1], H[2], H[3], H[4], H[5] | |
for j = 0, 19, 5 do | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j] + 0x5A827999 + e)) -- constant = floor(2^30 * sqrt(2)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j+1] + 0x5A827999 + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j+2] + 0x5A827999 + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j+3] + 0x5A827999 + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j+4] + 0x5A827999 + e)) | |
end | |
for j = 20, 39, 5 do | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j] + 0x6ED9EBA1 + e)) -- 2^30 * sqrt(3) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+1] + 0x6ED9EBA1 + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+2] + 0x6ED9EBA1 + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+3] + 0x6ED9EBA1 + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+4] + 0x6ED9EBA1 + e)) | |
end | |
for j = 40, 59, 5 do | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j] + 0x8F1BBCDC + e)) -- 2^30 * sqrt(5) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j+1] + 0x8F1BBCDC + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j+2] + 0x8F1BBCDC + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j+3] + 0x8F1BBCDC + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j+4] + 0x8F1BBCDC + e)) | |
end | |
for j = 60, 79, 5 do | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j] + 0xCA62C1D6 + e)) -- 2^30 * sqrt(10) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+1] + 0xCA62C1D6 + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+2] + 0xCA62C1D6 + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+3] + 0xCA62C1D6 + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+4] + 0xCA62C1D6 + e)) | |
end | |
H[1], H[2], H[3], H[4], H[5] = NORM(a + H[1]), NORM(b + H[2]), NORM(c + H[3]), NORM(d + H[4]), NORM(e + H[5]) | |
end | |
end | |
end | |
-- SHA3 implementation for "LuaJIT 2.0 + FFI" and "LuaJIT without FFI" branches | |
if branch == "FFI" and not is_LuaJIT_21 or branch == "LJ" then | |
if branch == "FFI" then | |
local lanes_arr32 = ffi.typeof"int32_t[31]" -- 25 + 5 + 1 (due to 1-based indexing) | |
function create_array_of_lanes() | |
return lanes_arr32() | |
end | |
end | |
function keccak_feed(lanes_lo, lanes_hi, str, offs, size, block_size_in_bytes) | |
-- offs >= 0, size >= 0, size is multiple of block_size_in_bytes, block_size_in_bytes is positive multiple of 8 | |
local RC_lo, RC_hi = sha3_RC_lo, sha3_RC_hi | |
local qwords_qty = SHR(block_size_in_bytes, 3) | |
for pos = offs, offs + size - 1, block_size_in_bytes do | |
for j = 1, qwords_qty do | |
local a, b, c, d = byte(str, pos + 1, pos + 4) | |
lanes_lo[j] = XOR(lanes_lo[j], OR(SHL(d, 24), SHL(c, 16), SHL(b, 8), a)) | |
pos = pos + 8 | |
a, b, c, d = byte(str, pos - 3, pos) | |
lanes_hi[j] = XOR(lanes_hi[j], OR(SHL(d, 24), SHL(c, 16), SHL(b, 8), a)) | |
end | |
for round_idx = 1, 24 do | |
for j = 1, 5 do | |
lanes_lo[25 + j] = XOR(lanes_lo[j], lanes_lo[j + 5], lanes_lo[j + 10], lanes_lo[j + 15], lanes_lo[j + 20]) | |
end | |
for j = 1, 5 do | |
lanes_hi[25 + j] = XOR(lanes_hi[j], lanes_hi[j + 5], lanes_hi[j + 10], lanes_hi[j + 15], lanes_hi[j + 20]) | |
end | |
local D_lo = XOR(lanes_lo[26], SHL(lanes_lo[28], 1), SHR(lanes_hi[28], 31)) | |
local D_hi = XOR(lanes_hi[26], SHL(lanes_hi[28], 1), SHR(lanes_lo[28], 31)) | |
lanes_lo[2], lanes_hi[2], lanes_lo[7], lanes_hi[7], lanes_lo[12], lanes_hi[12], lanes_lo[17], lanes_hi[17] = XOR(SHR(XOR(D_lo, lanes_lo[7]), 20), SHL(XOR(D_hi, lanes_hi[7]), 12)), XOR(SHR(XOR(D_hi, lanes_hi[7]), 20), SHL(XOR(D_lo, lanes_lo[7]), 12)), XOR(SHR(XOR(D_lo, lanes_lo[17]), 19), SHL(XOR(D_hi, lanes_hi[17]), 13)), XOR(SHR(XOR(D_hi, lanes_hi[17]), 19), SHL(XOR(D_lo, lanes_lo[17]), 13)), XOR(SHL(XOR(D_lo, lanes_lo[2]), 1), SHR(XOR(D_hi, lanes_hi[2]), 31)), XOR(SHL(XOR(D_hi, lanes_hi[2]), 1), SHR(XOR(D_lo, lanes_lo[2]), 31)), XOR(SHL(XOR(D_lo, lanes_lo[12]), 10), SHR(XOR(D_hi, lanes_hi[12]), 22)), XOR(SHL(XOR(D_hi, lanes_hi[12]), 10), SHR(XOR(D_lo, lanes_lo[12]), 22)) | |
local L, H = XOR(D_lo, lanes_lo[22]), XOR(D_hi, lanes_hi[22]) | |
lanes_lo[22], lanes_hi[22] = XOR(SHL(L, 2), SHR(H, 30)), XOR(SHL(H, 2), SHR(L, 30)) | |
D_lo = XOR(lanes_lo[27], SHL(lanes_lo[29], 1), SHR(lanes_hi[29], 31)) | |
D_hi = XOR(lanes_hi[27], SHL(lanes_hi[29], 1), SHR(lanes_lo[29], 31)) | |
lanes_lo[3], lanes_hi[3], lanes_lo[8], lanes_hi[8], lanes_lo[13], lanes_hi[13], lanes_lo[23], lanes_hi[23] = XOR(SHR(XOR(D_lo, lanes_lo[13]), 21), SHL(XOR(D_hi, lanes_hi[13]), 11)), XOR(SHR(XOR(D_hi, lanes_hi[13]), 21), SHL(XOR(D_lo, lanes_lo[13]), 11)), XOR(SHR(XOR(D_lo, lanes_lo[23]), 3), SHL(XOR(D_hi, lanes_hi[23]), 29)), XOR(SHR(XOR(D_hi, lanes_hi[23]), 3), SHL(XOR(D_lo, lanes_lo[23]), 29)), XOR(SHL(XOR(D_lo, lanes_lo[8]), 6), SHR(XOR(D_hi, lanes_hi[8]), 26)), XOR(SHL(XOR(D_hi, lanes_hi[8]), 6), SHR(XOR(D_lo, lanes_lo[8]), 26)), XOR(SHR(XOR(D_lo, lanes_lo[3]), 2), SHL(XOR(D_hi, lanes_hi[3]), 30)), XOR(SHR(XOR(D_hi, lanes_hi[3]), 2), SHL(XOR(D_lo, lanes_lo[3]), 30)) | |
L, H = XOR(D_lo, lanes_lo[18]), XOR(D_hi, lanes_hi[18]) | |
lanes_lo[18], lanes_hi[18] = XOR(SHL(L, 15), SHR(H, 17)), XOR(SHL(H, 15), SHR(L, 17)) | |
D_lo = XOR(lanes_lo[28], SHL(lanes_lo[30], 1), SHR(lanes_hi[30], 31)) | |
D_hi = XOR(lanes_hi[28], SHL(lanes_hi[30], 1), SHR(lanes_lo[30], 31)) | |
lanes_lo[4], lanes_hi[4], lanes_lo[9], lanes_hi[9], lanes_lo[19], lanes_hi[19], lanes_lo[24], lanes_hi[24] = XOR(SHL(XOR(D_lo, lanes_lo[19]), 21), SHR(XOR(D_hi, lanes_hi[19]), 11)), XOR(SHL(XOR(D_hi, lanes_hi[19]), 21), SHR(XOR(D_lo, lanes_lo[19]), 11)), XOR(SHL(XOR(D_lo, lanes_lo[4]), 28), SHR(XOR(D_hi, lanes_hi[4]), 4)), XOR(SHL(XOR(D_hi, lanes_hi[4]), 28), SHR(XOR(D_lo, lanes_lo[4]), 4)), XOR(SHR(XOR(D_lo, lanes_lo[24]), 8), SHL(XOR(D_hi, lanes_hi[24]), 24)), XOR(SHR(XOR(D_hi, lanes_hi[24]), 8), SHL(XOR(D_lo, lanes_lo[24]), 24)), XOR(SHR(XOR(D_lo, lanes_lo[9]), 9), SHL(XOR(D_hi, lanes_hi[9]), 23)), XOR(SHR(XOR(D_hi, lanes_hi[9]), 9), SHL(XOR(D_lo, lanes_lo[9]), 23)) | |
L, H = XOR(D_lo, lanes_lo[14]), XOR(D_hi, lanes_hi[14]) | |
lanes_lo[14], lanes_hi[14] = XOR(SHL(L, 25), SHR(H, 7)), XOR(SHL(H, 25), SHR(L, 7)) | |
D_lo = XOR(lanes_lo[29], SHL(lanes_lo[26], 1), SHR(lanes_hi[26], 31)) | |
D_hi = XOR(lanes_hi[29], SHL(lanes_hi[26], 1), SHR(lanes_lo[26], 31)) | |
lanes_lo[5], lanes_hi[5], lanes_lo[15], lanes_hi[15], lanes_lo[20], lanes_hi[20], lanes_lo[25], lanes_hi[25] = XOR(SHL(XOR(D_lo, lanes_lo[25]), 14), SHR(XOR(D_hi, lanes_hi[25]), 18)), XOR(SHL(XOR(D_hi, lanes_hi[25]), 14), SHR(XOR(D_lo, lanes_lo[25]), 18)), XOR(SHL(XOR(D_lo, lanes_lo[20]), 8), SHR(XOR(D_hi, lanes_hi[20]), 24)), XOR(SHL(XOR(D_hi, lanes_hi[20]), 8), SHR(XOR(D_lo, lanes_lo[20]), 24)), XOR(SHL(XOR(D_lo, lanes_lo[5]), 27), SHR(XOR(D_hi, lanes_hi[5]), 5)), XOR(SHL(XOR(D_hi, lanes_hi[5]), 27), SHR(XOR(D_lo, lanes_lo[5]), 5)), XOR(SHR(XOR(D_lo, lanes_lo[15]), 25), SHL(XOR(D_hi, lanes_hi[15]), 7)), XOR(SHR(XOR(D_hi, lanes_hi[15]), 25), SHL(XOR(D_lo, lanes_lo[15]), 7)) | |
L, H = XOR(D_lo, lanes_lo[10]), XOR(D_hi, lanes_hi[10]) | |
lanes_lo[10], lanes_hi[10] = XOR(SHL(L, 20), SHR(H, 12)), XOR(SHL(H, 20), SHR(L, 12)) | |
D_lo = XOR(lanes_lo[30], SHL(lanes_lo[27], 1), SHR(lanes_hi[27], 31)) | |
D_hi = XOR(lanes_hi[30], SHL(lanes_hi[27], 1), SHR(lanes_lo[27], 31)) | |
lanes_lo[6], lanes_hi[6], lanes_lo[11], lanes_hi[11], lanes_lo[16], lanes_hi[16], lanes_lo[21], lanes_hi[21] = XOR(SHL(XOR(D_lo, lanes_lo[11]), 3), SHR(XOR(D_hi, lanes_hi[11]), 29)), XOR(SHL(XOR(D_hi, lanes_hi[11]), 3), SHR(XOR(D_lo, lanes_lo[11]), 29)), XOR(SHL(XOR(D_lo, lanes_lo[21]), 18), SHR(XOR(D_hi, lanes_hi[21]), 14)), XOR(SHL(XOR(D_hi, lanes_hi[21]), 18), SHR(XOR(D_lo, lanes_lo[21]), 14)), XOR(SHR(XOR(D_lo, lanes_lo[6]), 28), SHL(XOR(D_hi, lanes_hi[6]), 4)), XOR(SHR(XOR(D_hi, lanes_hi[6]), 28), SHL(XOR(D_lo, lanes_lo[6]), 4)), XOR(SHR(XOR(D_lo, lanes_lo[16]), 23), SHL(XOR(D_hi, lanes_hi[16]), 9)), XOR(SHR(XOR(D_hi, lanes_hi[16]), 23), SHL(XOR(D_lo, lanes_lo[16]), 9)) | |
lanes_lo[1], lanes_hi[1] = XOR(D_lo, lanes_lo[1]), XOR(D_hi, lanes_hi[1]) | |
lanes_lo[1], lanes_lo[2], lanes_lo[3], lanes_lo[4], lanes_lo[5] = XOR(lanes_lo[1], AND(NOT(lanes_lo[2]), lanes_lo[3]), RC_lo[round_idx]), XOR(lanes_lo[2], AND(NOT(lanes_lo[3]), lanes_lo[4])), XOR(lanes_lo[3], AND(NOT(lanes_lo[4]), lanes_lo[5])), XOR(lanes_lo[4], AND(NOT(lanes_lo[5]), lanes_lo[1])), XOR(lanes_lo[5], AND(NOT(lanes_lo[1]), lanes_lo[2])) | |
lanes_lo[6], lanes_lo[7], lanes_lo[8], lanes_lo[9], lanes_lo[10] = XOR(lanes_lo[9], AND(NOT(lanes_lo[10]), lanes_lo[6])), XOR(lanes_lo[10], AND(NOT(lanes_lo[6]), lanes_lo[7])), XOR(lanes_lo[6], AND(NOT(lanes_lo[7]), lanes_lo[8])), XOR(lanes_lo[7], AND(NOT(lanes_lo[8]), lanes_lo[9])), XOR(lanes_lo[8], AND(NOT(lanes_lo[9]), lanes_lo[10])) | |
lanes_lo[11], lanes_lo[12], lanes_lo[13], lanes_lo[14], lanes_lo[15] = XOR(lanes_lo[12], AND(NOT(lanes_lo[13]), lanes_lo[14])), XOR(lanes_lo[13], AND(NOT(lanes_lo[14]), lanes_lo[15])), XOR(lanes_lo[14], AND(NOT(lanes_lo[15]), lanes_lo[11])), XOR(lanes_lo[15], AND(NOT(lanes_lo[11]), lanes_lo[12])), XOR(lanes_lo[11], AND(NOT(lanes_lo[12]), lanes_lo[13])) | |
lanes_lo[16], lanes_lo[17], lanes_lo[18], lanes_lo[19], lanes_lo[20] = XOR(lanes_lo[20], AND(NOT(lanes_lo[16]), lanes_lo[17])), XOR(lanes_lo[16], AND(NOT(lanes_lo[17]), lanes_lo[18])), XOR(lanes_lo[17], AND(NOT(lanes_lo[18]), lanes_lo[19])), XOR(lanes_lo[18], AND(NOT(lanes_lo[19]), lanes_lo[20])), XOR(lanes_lo[19], AND(NOT(lanes_lo[20]), lanes_lo[16])) | |
lanes_lo[21], lanes_lo[22], lanes_lo[23], lanes_lo[24], lanes_lo[25] = XOR(lanes_lo[23], AND(NOT(lanes_lo[24]), lanes_lo[25])), XOR(lanes_lo[24], AND(NOT(lanes_lo[25]), lanes_lo[21])), XOR(lanes_lo[25], AND(NOT(lanes_lo[21]), lanes_lo[22])), XOR(lanes_lo[21], AND(NOT(lanes_lo[22]), lanes_lo[23])), XOR(lanes_lo[22], AND(NOT(lanes_lo[23]), lanes_lo[24])) | |
lanes_hi[1], lanes_hi[2], lanes_hi[3], lanes_hi[4], lanes_hi[5] = XOR(lanes_hi[1], AND(NOT(lanes_hi[2]), lanes_hi[3]), RC_hi[round_idx]), XOR(lanes_hi[2], AND(NOT(lanes_hi[3]), lanes_hi[4])), XOR(lanes_hi[3], AND(NOT(lanes_hi[4]), lanes_hi[5])), XOR(lanes_hi[4], AND(NOT(lanes_hi[5]), lanes_hi[1])), XOR(lanes_hi[5], AND(NOT(lanes_hi[1]), lanes_hi[2])) | |
lanes_hi[6], lanes_hi[7], lanes_hi[8], lanes_hi[9], lanes_hi[10] = XOR(lanes_hi[9], AND(NOT(lanes_hi[10]), lanes_hi[6])), XOR(lanes_hi[10], AND(NOT(lanes_hi[6]), lanes_hi[7])), XOR(lanes_hi[6], AND(NOT(lanes_hi[7]), lanes_hi[8])), XOR(lanes_hi[7], AND(NOT(lanes_hi[8]), lanes_hi[9])), XOR(lanes_hi[8], AND(NOT(lanes_hi[9]), lanes_hi[10])) | |
lanes_hi[11], lanes_hi[12], lanes_hi[13], lanes_hi[14], lanes_hi[15] = XOR(lanes_hi[12], AND(NOT(lanes_hi[13]), lanes_hi[14])), XOR(lanes_hi[13], AND(NOT(lanes_hi[14]), lanes_hi[15])), XOR(lanes_hi[14], AND(NOT(lanes_hi[15]), lanes_hi[11])), XOR(lanes_hi[15], AND(NOT(lanes_hi[11]), lanes_hi[12])), XOR(lanes_hi[11], AND(NOT(lanes_hi[12]), lanes_hi[13])) | |
lanes_hi[16], lanes_hi[17], lanes_hi[18], lanes_hi[19], lanes_hi[20] = XOR(lanes_hi[20], AND(NOT(lanes_hi[16]), lanes_hi[17])), XOR(lanes_hi[16], AND(NOT(lanes_hi[17]), lanes_hi[18])), XOR(lanes_hi[17], AND(NOT(lanes_hi[18]), lanes_hi[19])), XOR(lanes_hi[18], AND(NOT(lanes_hi[19]), lanes_hi[20])), XOR(lanes_hi[19], AND(NOT(lanes_hi[20]), lanes_hi[16])) | |
lanes_hi[21], lanes_hi[22], lanes_hi[23], lanes_hi[24], lanes_hi[25] = XOR(lanes_hi[23], AND(NOT(lanes_hi[24]), lanes_hi[25])), XOR(lanes_hi[24], AND(NOT(lanes_hi[25]), lanes_hi[21])), XOR(lanes_hi[25], AND(NOT(lanes_hi[21]), lanes_hi[22])), XOR(lanes_hi[21], AND(NOT(lanes_hi[22]), lanes_hi[23])), XOR(lanes_hi[22], AND(NOT(lanes_hi[23]), lanes_hi[24])) | |
end | |
end | |
end | |
end | |
if branch == "LJ" then | |
-- SHA256 implementation for "LuaJIT without FFI" branch | |
function sha256_feed_64(H, str, offs, size) | |
-- offs >= 0, size >= 0, size is multiple of 64 | |
local W, K = common_W, sha2_K_hi | |
for pos = offs, offs + size - 1, 64 do | |
for j = 1, 16 do | |
pos = pos + 4 | |
local a, b, c, d = byte(str, pos - 3, pos) | |
W[j] = OR(SHL(a, 24), SHL(b, 16), SHL(c, 8), d) | |
end | |
for j = 17, 64 do | |
local a, b = W[j-15], W[j-2] | |
W[j] = NORM( NORM( XOR(ROR(a, 7), ROL(a, 14), SHR(a, 3)) + XOR(ROL(b, 15), ROL(b, 13), SHR(b, 10)) ) + NORM( W[j-7] + W[j-16] ) ) | |
end | |
local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8] | |
for j = 1, 64, 8 do -- Thanks to Peter Cawley for this workaround (unroll the loop to avoid "PHI shuffling too complex" due to PHIs overlap) | |
local z = NORM( XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + XOR(g, AND(e, XOR(f, g))) + (K[j] + W[j] + h) ) | |
h, g, f, e = g, f, e, NORM(d + z) | |
d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z ) | |
z = NORM( XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + XOR(g, AND(e, XOR(f, g))) + (K[j+1] + W[j+1] + h) ) | |
h, g, f, e = g, f, e, NORM(d + z) | |
d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z ) | |
z = NORM( XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + XOR(g, AND(e, XOR(f, g))) + (K[j+2] + W[j+2] + h) ) | |
h, g, f, e = g, f, e, NORM(d + z) | |
d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z ) | |
z = NORM( XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + XOR(g, AND(e, XOR(f, g))) + (K[j+3] + W[j+3] + h) ) | |
h, g, f, e = g, f, e, NORM(d + z) | |
d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z ) | |
z = NORM( XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + XOR(g, AND(e, XOR(f, g))) + (K[j+4] + W[j+4] + h) ) | |
h, g, f, e = g, f, e, NORM(d + z) | |
d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z ) | |
z = NORM( XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + XOR(g, AND(e, XOR(f, g))) + (K[j+5] + W[j+5] + h) ) | |
h, g, f, e = g, f, e, NORM(d + z) | |
d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z ) | |
z = NORM( XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + XOR(g, AND(e, XOR(f, g))) + (K[j+6] + W[j+6] + h) ) | |
h, g, f, e = g, f, e, NORM(d + z) | |
d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z ) | |
z = NORM( XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + XOR(g, AND(e, XOR(f, g))) + (K[j+7] + W[j+7] + h) ) | |
h, g, f, e = g, f, e, NORM(d + z) | |
d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z ) | |
end | |
H[1], H[2], H[3], H[4] = NORM(a + H[1]), NORM(b + H[2]), NORM(c + H[3]), NORM(d + H[4]) | |
H[5], H[6], H[7], H[8] = NORM(e + H[5]), NORM(f + H[6]), NORM(g + H[7]), NORM(h + H[8]) | |
end | |
end | |
local function ADD64_4(a_lo, a_hi, b_lo, b_hi, c_lo, c_hi, d_lo, d_hi) | |
local sum_lo = a_lo % 2^32 + b_lo % 2^32 + c_lo % 2^32 + d_lo % 2^32 | |
local sum_hi = a_hi + b_hi + c_hi + d_hi | |
local result_lo = NORM( sum_lo ) | |
local result_hi = NORM( sum_hi + floor(sum_lo / 2^32) ) | |
return result_lo, result_hi | |
end | |
if LuaJIT_arch == "x86" then -- Special trick is required to avoid "PHI shuffling too complex" on x86 platform | |
-- SHA512 implementation for "LuaJIT x86 without FFI" branch | |
function sha512_feed_128(H_lo, H_hi, str, offs, size) | |
-- offs >= 0, size >= 0, size is multiple of 128 | |
-- W1_hi, W1_lo, W2_hi, W2_lo, ... Wk_hi = W[2*k-1], Wk_lo = W[2*k] | |
local W, K_lo, K_hi = common_W, sha2_K_lo, sha2_K_hi | |
for pos = offs, offs + size - 1, 128 do | |
for j = 1, 16*2 do | |
pos = pos + 4 | |
local a, b, c, d = byte(str, pos - 3, pos) | |
W[j] = OR(SHL(a, 24), SHL(b, 16), SHL(c, 8), d) | |
end | |
for jj = 17*2, 80*2, 2 do | |
local a_lo, a_hi = W[jj-30], W[jj-31] | |
local t_lo = XOR(OR(SHR(a_lo, 1), SHL(a_hi, 31)), OR(SHR(a_lo, 8), SHL(a_hi, 24)), OR(SHR(a_lo, 7), SHL(a_hi, 25))) | |
local t_hi = XOR(OR(SHR(a_hi, 1), SHL(a_lo, 31)), OR(SHR(a_hi, 8), SHL(a_lo, 24)), SHR(a_hi, 7)) | |
local b_lo, b_hi = W[jj-4], W[jj-5] | |
local u_lo = XOR(OR(SHR(b_lo, 19), SHL(b_hi, 13)), OR(SHL(b_lo, 3), SHR(b_hi, 29)), OR(SHR(b_lo, 6), SHL(b_hi, 26))) | |
local u_hi = XOR(OR(SHR(b_hi, 19), SHL(b_lo, 13)), OR(SHL(b_hi, 3), SHR(b_lo, 29)), SHR(b_hi, 6)) | |
W[jj], W[jj-1] = ADD64_4(t_lo, t_hi, u_lo, u_hi, W[jj-14], W[jj-15], W[jj-32], W[jj-33]) | |
end | |
local a_lo, b_lo, c_lo, d_lo, e_lo, f_lo, g_lo, h_lo = H_lo[1], H_lo[2], H_lo[3], H_lo[4], H_lo[5], H_lo[6], H_lo[7], H_lo[8] | |
local a_hi, b_hi, c_hi, d_hi, e_hi, f_hi, g_hi, h_hi = H_hi[1], H_hi[2], H_hi[3], H_hi[4], H_hi[5], H_hi[6], H_hi[7], H_hi[8] | |
local zero = 0 | |
for j = 1, 80 do | |
local t_lo = XOR(g_lo, AND(e_lo, XOR(f_lo, g_lo))) | |
local t_hi = XOR(g_hi, AND(e_hi, XOR(f_hi, g_hi))) | |
local u_lo = XOR(OR(SHR(e_lo, 14), SHL(e_hi, 18)), OR(SHR(e_lo, 18), SHL(e_hi, 14)), OR(SHL(e_lo, 23), SHR(e_hi, 9))) | |
local u_hi = XOR(OR(SHR(e_hi, 14), SHL(e_lo, 18)), OR(SHR(e_hi, 18), SHL(e_lo, 14)), OR(SHL(e_hi, 23), SHR(e_lo, 9))) | |
local sum_lo = u_lo % 2^32 + t_lo % 2^32 + h_lo % 2^32 + K_lo[j] + W[2*j] % 2^32 | |
local z_lo, z_hi = NORM( sum_lo ), NORM( u_hi + t_hi + h_hi + K_hi[j] + W[2*j-1] + floor(sum_lo / 2^32) ) | |
zero = zero + zero -- this thick is needed to avoid "PHI shuffling too complex" due to PHIs overlap | |
h_lo, h_hi, g_lo, g_hi, f_lo, f_hi = OR(zero, g_lo), OR(zero, g_hi), OR(zero, f_lo), OR(zero, f_hi), OR(zero, e_lo), OR(zero, e_hi) | |
local sum_lo = z_lo % 2^32 + d_lo % 2^32 | |
e_lo, e_hi = NORM( sum_lo ), NORM( z_hi + d_hi + floor(sum_lo / 2^32) ) | |
d_lo, d_hi, c_lo, c_hi, b_lo, b_hi = OR(zero, c_lo), OR(zero, c_hi), OR(zero, b_lo), OR(zero, b_hi), OR(zero, a_lo), OR(zero, a_hi) | |
u_lo = XOR(OR(SHR(b_lo, 28), SHL(b_hi, 4)), OR(SHL(b_lo, 30), SHR(b_hi, 2)), OR(SHL(b_lo, 25), SHR(b_hi, 7))) | |
u_hi = XOR(OR(SHR(b_hi, 28), SHL(b_lo, 4)), OR(SHL(b_hi, 30), SHR(b_lo, 2)), OR(SHL(b_hi, 25), SHR(b_lo, 7))) | |
t_lo = OR(AND(d_lo, c_lo), AND(b_lo, XOR(d_lo, c_lo))) | |
t_hi = OR(AND(d_hi, c_hi), AND(b_hi, XOR(d_hi, c_hi))) | |
local sum_lo = z_lo % 2^32 + t_lo % 2^32 + u_lo % 2^32 | |
a_lo, a_hi = NORM( sum_lo ), NORM( z_hi + t_hi + u_hi + floor(sum_lo / 2^32) ) | |
end | |
H_lo[1], H_hi[1] = ADD64_4(H_lo[1], H_hi[1], a_lo, a_hi, 0, 0, 0, 0) | |
H_lo[2], H_hi[2] = ADD64_4(H_lo[2], H_hi[2], b_lo, b_hi, 0, 0, 0, 0) | |
H_lo[3], H_hi[3] = ADD64_4(H_lo[3], H_hi[3], c_lo, c_hi, 0, 0, 0, 0) | |
H_lo[4], H_hi[4] = ADD64_4(H_lo[4], H_hi[4], d_lo, d_hi, 0, 0, 0, 0) | |
H_lo[5], H_hi[5] = ADD64_4(H_lo[5], H_hi[5], e_lo, e_hi, 0, 0, 0, 0) | |
H_lo[6], H_hi[6] = ADD64_4(H_lo[6], H_hi[6], f_lo, f_hi, 0, 0, 0, 0) | |
H_lo[7], H_hi[7] = ADD64_4(H_lo[7], H_hi[7], g_lo, g_hi, 0, 0, 0, 0) | |
H_lo[8], H_hi[8] = ADD64_4(H_lo[8], H_hi[8], h_lo, h_hi, 0, 0, 0, 0) | |
end | |
end | |
else -- all platforms except x86 | |
-- SHA512 implementation for "LuaJIT non-x86 without FFI" branch | |
function sha512_feed_128(H_lo, H_hi, str, offs, size) | |
-- offs >= 0, size >= 0, size is multiple of 128 | |
-- W1_hi, W1_lo, W2_hi, W2_lo, ... Wk_hi = W[2*k-1], Wk_lo = W[2*k] | |
local W, K_lo, K_hi = common_W, sha2_K_lo, sha2_K_hi | |
for pos = offs, offs + size - 1, 128 do | |
for j = 1, 16*2 do | |
pos = pos + 4 | |
local a, b, c, d = byte(str, pos - 3, pos) | |
W[j] = OR(SHL(a, 24), SHL(b, 16), SHL(c, 8), d) | |
end | |
for jj = 17*2, 80*2, 2 do | |
local a_lo, a_hi = W[jj-30], W[jj-31] | |
local t_lo = XOR(OR(SHR(a_lo, 1), SHL(a_hi, 31)), OR(SHR(a_lo, 8), SHL(a_hi, 24)), OR(SHR(a_lo, 7), SHL(a_hi, 25))) | |
local t_hi = XOR(OR(SHR(a_hi, 1), SHL(a_lo, 31)), OR(SHR(a_hi, 8), SHL(a_lo, 24)), SHR(a_hi, 7)) | |
local b_lo, b_hi = W[jj-4], W[jj-5] | |
local u_lo = XOR(OR(SHR(b_lo, 19), SHL(b_hi, 13)), OR(SHL(b_lo, 3), SHR(b_hi, 29)), OR(SHR(b_lo, 6), SHL(b_hi, 26))) | |
local u_hi = XOR(OR(SHR(b_hi, 19), SHL(b_lo, 13)), OR(SHL(b_hi, 3), SHR(b_lo, 29)), SHR(b_hi, 6)) | |
W[jj], W[jj-1] = ADD64_4(t_lo, t_hi, u_lo, u_hi, W[jj-14], W[jj-15], W[jj-32], W[jj-33]) | |
end | |
local a_lo, b_lo, c_lo, d_lo, e_lo, f_lo, g_lo, h_lo = H_lo[1], H_lo[2], H_lo[3], H_lo[4], H_lo[5], H_lo[6], H_lo[7], H_lo[8] | |
local a_hi, b_hi, c_hi, d_hi, e_hi, f_hi, g_hi, h_hi = H_hi[1], H_hi[2], H_hi[3], H_hi[4], H_hi[5], H_hi[6], H_hi[7], H_hi[8] | |
for j = 1, 80 do | |
local t_lo = XOR(g_lo, AND(e_lo, XOR(f_lo, g_lo))) | |
local t_hi = XOR(g_hi, AND(e_hi, XOR(f_hi, g_hi))) | |
local u_lo = XOR(OR(SHR(e_lo, 14), SHL(e_hi, 18)), OR(SHR(e_lo, 18), SHL(e_hi, 14)), OR(SHL(e_lo, 23), SHR(e_hi, 9))) | |
local u_hi = XOR(OR(SHR(e_hi, 14), SHL(e_lo, 18)), OR(SHR(e_hi, 18), SHL(e_lo, 14)), OR(SHL(e_hi, 23), SHR(e_lo, 9))) | |
local sum_lo = u_lo % 2^32 + t_lo % 2^32 + h_lo % 2^32 + K_lo[j] + W[2*j] % 2^32 | |
local z_lo, z_hi = NORM( sum_lo ), NORM( u_hi + t_hi + h_hi + K_hi[j] + W[2*j-1] + floor(sum_lo / 2^32) ) | |
h_lo, h_hi, g_lo, g_hi, f_lo, f_hi = g_lo, g_hi, f_lo, f_hi, e_lo, e_hi | |
local sum_lo = z_lo % 2^32 + d_lo % 2^32 | |
e_lo, e_hi = NORM( sum_lo ), NORM( z_hi + d_hi + floor(sum_lo / 2^32) ) | |
d_lo, d_hi, c_lo, c_hi, b_lo, b_hi = c_lo, c_hi, b_lo, b_hi, a_lo, a_hi | |
u_lo = XOR(OR(SHR(b_lo, 28), SHL(b_hi, 4)), OR(SHL(b_lo, 30), SHR(b_hi, 2)), OR(SHL(b_lo, 25), SHR(b_hi, 7))) | |
u_hi = XOR(OR(SHR(b_hi, 28), SHL(b_lo, 4)), OR(SHL(b_hi, 30), SHR(b_lo, 2)), OR(SHL(b_hi, 25), SHR(b_lo, 7))) | |
t_lo = OR(AND(d_lo, c_lo), AND(b_lo, XOR(d_lo, c_lo))) | |
t_hi = OR(AND(d_hi, c_hi), AND(b_hi, XOR(d_hi, c_hi))) | |
local sum_lo = z_lo % 2^32 + u_lo % 2^32 + t_lo % 2^32 | |
a_lo, a_hi = NORM( sum_lo ), NORM( z_hi + u_hi + t_hi + floor(sum_lo / 2^32) ) | |
end | |
H_lo[1], H_hi[1] = ADD64_4(H_lo[1], H_hi[1], a_lo, a_hi, 0, 0, 0, 0) | |
H_lo[2], H_hi[2] = ADD64_4(H_lo[2], H_hi[2], b_lo, b_hi, 0, 0, 0, 0) | |
H_lo[3], H_hi[3] = ADD64_4(H_lo[3], H_hi[3], c_lo, c_hi, 0, 0, 0, 0) | |
H_lo[4], H_hi[4] = ADD64_4(H_lo[4], H_hi[4], d_lo, d_hi, 0, 0, 0, 0) | |
H_lo[5], H_hi[5] = ADD64_4(H_lo[5], H_hi[5], e_lo, e_hi, 0, 0, 0, 0) | |
H_lo[6], H_hi[6] = ADD64_4(H_lo[6], H_hi[6], f_lo, f_hi, 0, 0, 0, 0) | |
H_lo[7], H_hi[7] = ADD64_4(H_lo[7], H_hi[7], g_lo, g_hi, 0, 0, 0, 0) | |
H_lo[8], H_hi[8] = ADD64_4(H_lo[8], H_hi[8], h_lo, h_hi, 0, 0, 0, 0) | |
end | |
end | |
end | |
-- MD5 implementation for "LuaJIT without FFI" branch | |
function md5_feed_64(H, str, offs, size) | |
-- offs >= 0, size >= 0, size is multiple of 64 | |
local W, K = common_W, md5_K | |
for pos = offs, offs + size - 1, 64 do | |
for j = 1, 16 do | |
pos = pos + 4 | |
local a, b, c, d = byte(str, pos - 3, pos) | |
W[j] = OR(SHL(d, 24), SHL(c, 16), SHL(b, 8), a) | |
end | |
local a, b, c, d = H[1], H[2], H[3], H[4] | |
for j = 1, 16, 4 do | |
a, d, c, b = d, c, b, NORM(ROL(XOR(d, AND(b, XOR(c, d))) + (K[j ] + W[j ] + a), 7) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(d, AND(b, XOR(c, d))) + (K[j+1] + W[j+1] + a), 12) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(d, AND(b, XOR(c, d))) + (K[j+2] + W[j+2] + a), 17) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(d, AND(b, XOR(c, d))) + (K[j+3] + W[j+3] + a), 22) + b) | |
end | |
for j = 17, 32, 4 do | |
local g = 5*j-4 | |
a, d, c, b = d, c, b, NORM(ROL(XOR(c, AND(d, XOR(b, c))) + (K[j ] + W[AND(g , 15) + 1] + a), 5) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(c, AND(d, XOR(b, c))) + (K[j+1] + W[AND(g + 5, 15) + 1] + a), 9) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(c, AND(d, XOR(b, c))) + (K[j+2] + W[AND(g + 10, 15) + 1] + a), 14) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(c, AND(d, XOR(b, c))) + (K[j+3] + W[AND(g - 1, 15) + 1] + a), 20) + b) | |
end | |
for j = 33, 48, 4 do | |
local g = 3*j+2 | |
a, d, c, b = d, c, b, NORM(ROL(XOR(b, c, d) + (K[j ] + W[AND(g , 15) + 1] + a), 4) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(b, c, d) + (K[j+1] + W[AND(g + 3, 15) + 1] + a), 11) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(b, c, d) + (K[j+2] + W[AND(g + 6, 15) + 1] + a), 16) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(b, c, d) + (K[j+3] + W[AND(g - 7, 15) + 1] + a), 23) + b) | |
end | |
for j = 49, 64, 4 do | |
local g = j*7 | |
a, d, c, b = d, c, b, NORM(ROL(XOR(c, OR(b, NOT(d))) + (K[j ] + W[AND(g - 7, 15) + 1] + a), 6) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(c, OR(b, NOT(d))) + (K[j+1] + W[AND(g , 15) + 1] + a), 10) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(c, OR(b, NOT(d))) + (K[j+2] + W[AND(g + 7, 15) + 1] + a), 15) + b) | |
a, d, c, b = d, c, b, NORM(ROL(XOR(c, OR(b, NOT(d))) + (K[j+3] + W[AND(g - 2, 15) + 1] + a), 21) + b) | |
end | |
H[1], H[2], H[3], H[4] = NORM(a + H[1]), NORM(b + H[2]), NORM(c + H[3]), NORM(d + H[4]) | |
end | |
end | |
-- SHA-1 implementation for "LuaJIT without FFI" branch | |
function sha1_feed_64(H, str, offs, size) | |
-- offs >= 0, size >= 0, size is multiple of 64 | |
local W = common_W | |
for pos = offs, offs + size - 1, 64 do | |
for j = 1, 16 do | |
pos = pos + 4 | |
local a, b, c, d = byte(str, pos - 3, pos) | |
W[j] = OR(SHL(a, 24), SHL(b, 16), SHL(c, 8), d) | |
end | |
for j = 17, 80 do | |
W[j] = ROL(XOR(W[j-3], W[j-8], W[j-14], W[j-16]), 1) | |
end | |
local a, b, c, d, e = H[1], H[2], H[3], H[4], H[5] | |
for j = 1, 20, 5 do | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j] + 0x5A827999 + e)) -- constant = floor(2^30 * sqrt(2)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j+1] + 0x5A827999 + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j+2] + 0x5A827999 + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j+3] + 0x5A827999 + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j+4] + 0x5A827999 + e)) | |
end | |
for j = 21, 40, 5 do | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j] + 0x6ED9EBA1 + e)) -- 2^30 * sqrt(3) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+1] + 0x6ED9EBA1 + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+2] + 0x6ED9EBA1 + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+3] + 0x6ED9EBA1 + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+4] + 0x6ED9EBA1 + e)) | |
end | |
for j = 41, 60, 5 do | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j] + 0x8F1BBCDC + e)) -- 2^30 * sqrt(5) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j+1] + 0x8F1BBCDC + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j+2] + 0x8F1BBCDC + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j+3] + 0x8F1BBCDC + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j+4] + 0x8F1BBCDC + e)) | |
end | |
for j = 61, 80, 5 do | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j] + 0xCA62C1D6 + e)) -- 2^30 * sqrt(10) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+1] + 0xCA62C1D6 + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+2] + 0xCA62C1D6 + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+3] + 0xCA62C1D6 + e)) | |
e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+4] + 0xCA62C1D6 + e)) | |
end | |
H[1], H[2], H[3], H[4], H[5] = NORM(a + H[1]), NORM(b + H[2]), NORM(c + H[3]), NORM(d + H[4]), NORM(e + H[5]) | |
end | |
end | |
end | |
if branch == "INT64" then | |
-- implementation for Lua 5.3/5.4 | |
hi_factor = 4294967296 | |
hi_factor_keccak = 4294967296 | |
lanes_index_base = 1 | |
HEX64, XOR64A5, XOR_BYTE, sha256_feed_64, sha512_feed_128, md5_feed_64, sha1_feed_64, keccak_feed = load[[local a,b,c,d,e,f=...local g,h=string.format,string.unpack;local function i(j)return g("%016x",j)end;local function k(j)return j~0xa5a5a5a5a5a5a5a5 end;local function l(j,m)return j~m end;local n={}local function o(p,q,r,s)local t,u=n,d;local v,w,x,y,z,A,B,C=p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8]for D=r+1,r+s,64 do t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15],t[16]=h(">I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4",q,D)for E=17,64 do local F=t[E-15]F=F<<32|F;local G=t[E-2]G=G<<32|G;t[E]=F>>7~(F>>18)~(F>>35)+G>>17~(G>>19)~(G>>42)+t[E-7]+t[E-16]&1<<32-1 end;local F,G,H,I,J,K,L,M=v,w,x,y,z,A,B,C;for E=1,64 do J=J<<32|(J&1<<32-1)local N=J>>6~(J>>11)~(J>>25)+L~(J&(K~L))+M+u[E]+t[E]M=L;L=K;K=J;J=N+I;I=H;H=G;G=F;F=F<<32|(F&1<<32-1)F=N+F~H&I~(F&H)+F>>2~(F>>13)~(F>>22)end;v=F+v;w=G+w;x=H+x;y=I+y;z=J+z;A=K+A;B=L+B;C=M+C end;p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8]=v,w,x,y,z,A,B,C end;local function O(p,P,q,r,s)local t,u=n,c;local v,w,x,y,z,A,B,C=p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8]for D=r+1,r+s,128 do t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15],t[16]=h(">i8i8i8i8i8i8i8i8i8i8i8i8i8i8i8i8",q,D)for E=17,80 do local F=t[E-15]local G=t[E-2]t[E]=F>>1~(F>>7)~(F>>8)~(F<<56)~(F<<63)+G>>6~(G>>19)~(G>>61)~(G<<3)~(G<<45)+t[E-7]+t[E-16]end;local F,G,H,I,J,K,L,M=v,w,x,y,z,A,B,C;for E=1,80 do local N=J>>14~(J>>18)~(J>>41)~(J<<23)~(J<<46)~(J<<50)+L~(J&(K~L))+M+u[E]+t[E]M=L;L=K;K=J;J=N+I;I=H;H=G;G=F;F=N+F~H&I~(F&H)+F>>28~(F>>34)~(F>>39)~(F<<25)~(F<<30)~(F<<36)end;v=F+v;w=G+w;x=H+x;y=I+y;z=J+z;A=K+A;B=L+B;C=M+C end;p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8]=v,w,x,y,z,A,B,C end;local function Q(p,q,r,s)local t,u,a=n,b,a;local v,w,x,y=p[1],p[2],p[3],p[4]for D=r+1,r+s,64 do t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15],t[16]=h("<I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4",q,D)local F,G,H,I=v,w,x,y;local R=32-7;for E=1,16 do local S=I~(G&(H~I))+F+u[E]+t[E]F=I;I=H;H=G;G=S<<32|(S&1<<32-1)>>R+G;R=a[R]end;R=32-5;for E=17,32 do local S=H~(I&(G~H))+F+u[E]+t[5*E-4&15+1]F=I;I=H;H=G;G=S<<32|(S&1<<32-1)>>R+G;R=a[R]end;R=32-4;for E=33,48 do local S=G~H~I+F+u[E]+t[3*E+2&15+1]F=I;I=H;H=G;G=S<<32|(S&1<<32-1)>>R+G;R=a[R]end;R=32-6;for E=49,64 do local S=H~(G|~I)+F+u[E]+t[E*7-7&15+1]F=I;I=H;H=G;G=S<<32|(S&1<<32-1)>>R+G;R=a[R]end;v=F+v;w=G+w;x=H+x;y=I+y end;p[1],p[2],p[3],p[4]=v,w,x,y end;local function T(p,q,r,s)local t=n;local v,w,x,y,z=p[1],p[2],p[3],p[4],p[5]for D=r+1,r+s,64 do t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15],t[16]=h(">I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4",q,D)for E=17,80 do local F=t[E-3]~t[E-8]~t[E-14]~t[E-16]t[E]=F<<32|F<<1>>32 end;local F,G,H,I,J=v,w,x,y,z;for E=1,20 do local N=F<<32|(F&1<<32-1)>>27+I~(G&(H~I))+0x5A827999+t[E]+J;J=I;I=H;H=G<<32|(G&1<<32-1)>>2;G=F;F=N end;for E=21,40 do local N=F<<32|(F&1<<32-1)>>27+G~H~I+0x6ED9EBA1+t[E]+J;J=I;I=H;H=G<<32|(G&1<<32-1)>>2;G=F;F=N end;for E=41,60 do local N=F<<32|(F&1<<32-1)>>27+G~H&I~(G&H)+0x8F1BBCDC+t[E]+J;J=I;I=H;H=G<<32|(G&1<<32-1)>>2;G=F;F=N end;for E=61,80 do local N=F<<32|(F&1<<32-1)>>27+G~H~I+0xCA62C1D6+t[E]+J;J=I;I=H;H=G<<32|(G&1<<32-1)>>2;G=F;F=N end;v=F+v;w=G+w;x=H+x;y=I+y;z=J+z end;p[1],p[2],p[3],p[4],p[5]=v,w,x,y,z end;local U=e("i8")local function V(W,P,q,r,s,X)local Y=f;local Z=X/8;local _=U[Z]for D=r+1,r+s,X do local a0={h(_,q,D)}for E=1,Z do W[E]=W[E]~a0[E]end;local a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,ab,ac,ad,ae,af,ag,ah,ai,aj,ak,al,am,an,ao,ap=W[1],W[2],W[3],W[4],W[5],W[6],W[7],W[8],W[9],W[10],W[11],W[12],W[13],W[14],W[15],W[16],W[17],W[18],W[19],W[20],W[21],W[22],W[23],W[24],W[25]for aq=1,24 do local ar=a1~a6~ab~ag~al;local as=a2~a7~ac~ah~am;local at=a3~a8~ad~ai~an;local au=a4~a9~ae~aj~ao;local av=a5~aa~af~ak~ap;local aw=ar~(at<<1)~(at>>63)local ax=aw~a2;local ay=aw~a7;local az=aw~ac;local aA=aw~ah;local aB=aw~am;a2=ay<<44~(ay>>20)a7=aA<<45~(aA>>19)ac=ax<<1~(ax>>63)ah=az<<10~(az>>54)am=aB<<2~(aB>>62)aw=as~(au<<1)~(au>>63)ax=aw~a3;ay=aw~a8;az=aw~ad;aA=aw~ai;aB=aw~an;a3=az<<43~(az>>21)a8=aB<<61~(aB>>3)ad=ay<<6~(ay>>58)ai=aA<<15~(aA>>49)an=ax<<62~(ax>>2)aw=at~(av<<1)~(av>>63)ax=aw~a4;ay=aw~a9;az=aw~ae;aA=aw~aj;aB=aw~ao;a4=aA<<21~(aA>>43)a9=ax<<28~(ax>>36)ae=az<<25~(az>>39)aj=aB<<56~(aB>>8)ao=ay<<55~(ay>>9)aw=au~(ar<<1)~(ar>>63)ax=aw~a5;ay=aw~aa;az=aw~af;aA=aw~ak;aB=aw~ap;a5=aB<<14~(aB>>50)aa=ay<<20~(ay>>44)af=aA<<8~(aA>>56)ak=ax<<27~(ax>>37)ap=az<<39~(az>>25)aw=av~(as<<1)~(as>>63)ay=aw~a6;az=aw~ab;aA=aw~ag;aB=aw~al;a6=az<<3~(az>>61)ab=aB<<18~(aB>>46)ag=ay<<36~(ay>>28)al=aA<<41~(aA>>23)a1=aw~a1;a1,a2,a3,a4,a5=a1~(~a2&a3),a2~(~a3&a4),a3~(~a4&a5),a4~(~a5&a1),a5~(~a1&a2)a6,a7,a8,a9,aa=a9~(~aa&a6),aa~(~a6&a7),a6~(~a7&a8),a7~(~a8&a9),a8~(~a9&aa)ab,ac,ad,ae,af=ac~(~ad&ae),ad~(~ae&af),ae~(~af&ab),af~(~ab&ac),ab~(~ac&ad)ag,ah,ai,aj,ak=ak~(~ag&ah),ag~(~ah&ai),ah~(~ai&aj),ai~(~aj&ak),aj~(~ak&ag)al,am,an,ao,ap=an~(~ao&ap),ao~(~ap&al),ap~(~al&am),al~(~am&an),am~(~an&ao)a1=a1~Y[aq]end;W[1]=a1;W[2]=a2;W[3]=a3;W[4]=a4;W[5]=a5;W[6]=a6;W[7]=a7;W[8]=a8;W[9]=a9;W[10]=aa;W[11]=ab;W[12]=ac;W[13]=ad;W[14]=ae;W[15]=af;W[16]=ag;W[17]=ah;W[18]=ai;W[19]=aj;W[20]=ak;W[21]=al;W[22]=am;W[23]=an;W[24]=ao;W[25]=ap end end;return i,k,l,o,O,Q,T,V]](md5_next_shift, md5_K, sha2_K_lo, sha2_K_hi, build_keccak_format, sha3_RC_lo) | |
end | |
if branch == "INT32" then | |
-- implementation for Lua 5.3/5.4 having non-standard numbers config "int32"+"double" (built with LUA_INT_TYPE=LUA_INT_INT) | |
K_lo_modulo = 2^32 | |
function HEX(x) -- returns string of 8 lowercase hexadecimal digits | |
return string_format("%08x", x) | |
end | |
XOR32A5, XOR_BYTE, sha256_feed_64, sha512_feed_128, md5_feed_64, sha1_feed_64, keccak_feed = load[[local a,b,c,d,e,f,g=...local h,i=string.unpack,math.floor;local function j(k)return k~0xA5A5A5A5 end;local function l(k,m)return k~m end;local n={}local function o(p,q,r,s)local t,u=n,d;local v,w,x,y,z,A,B,C=p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8]for D=r+1,r+s,64 do t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15],t[16]=h(">i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4",q,D)for E=17,64 do local F,G=t[E-15],t[E-2]t[E]=F>>7~(F<<25)~(F<<14)~(F>>18)~(F>>3)+G<<15~(G>>17)~(G<<13)~(G>>19)~(G>>10)+t[E-7]+t[E-16]end;local F,G,H,I,J,K,L,M=v,w,x,y,z,A,B,C;for E=1,64 do local N=J>>6~(J<<26)~(J>>11)~(J<<21)~(J>>25)~(J<<7)+L~(J&(K~L))+M+u[E]+t[E]M=L;L=K;K=J;J=N+I;I=H;H=G;G=F;F=N+F~H&I~(F&H)+F>>2~(F<<30)~(F>>13)~(F<<19)~(F<<10)~(F>>22)end;v=F+v;w=G+w;x=H+x;y=I+y;z=J+z;A=K+A;B=L+B;C=M+C end;p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8]=v,w,x,y,z,A,B,C end;local function O(P,Q,q,r,s)local i,t,R,S=i,n,c,d;local T,U,V,W,X,Y,Z,_=P[1],P[2],P[3],P[4],P[5],P[6],P[7],P[8]local a0,a1,a2,a3,a4,a5,a6,a7=Q[1],Q[2],Q[3],Q[4],Q[5],Q[6],Q[7],Q[8]for D=r+1,r+s,128 do t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15],t[16],t[17],t[18],t[19],t[20],t[21],t[22],t[23],t[24],t[25],t[26],t[27],t[28],t[29],t[30],t[31],t[32]=h(">i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4",q,D)for a8=17*2,80*2,2 do local a9,aa,ab,ac=t[a8-30],t[a8-31],t[a8-4],t[a8-5]local ad=a9>>1~(aa<<31)~(a9>>8)~(aa<<24)~(a9>>7)~(aa<<25)%2^32+ab>>19~(ac<<13)~(ab<<3)~(ac>>29)~(ab>>6)~(ac<<26)%2^32+t[a8-14]%2^32+t[a8-32]%2^32;t[a8-1]=aa>>1~(a9<<31)~(aa>>8)~(a9<<24)~(aa>>7)+ac>>19~(ab<<13)~(ac<<3)~(ab>>29)~(ac>>6)+t[a8-15]+t[a8-33]+i(ad/2^32)t[a8]=0|(ad+2^31)%2^32-2^31 end;local a9,ab,ae,af,ag,ah,ai,aj=T,U,V,W,X,Y,Z,_;local aa,ac,ak,al,am,an,ao,ap=a0,a1,a2,a3,a4,a5,a6,a7;for E=1,80 do local a8=2*E;local aq=ag>>14~(am<<18)~(ag>>18)~(am<<14)~(ag<<23)~(am>>9)%2^32+ai~(ag&(ah~ai))%2^32+aj%2^32+R[E]+t[a8]%2^32;local ar=am>>14~(ag<<18)~(am>>18)~(ag<<14)~(am<<23)~(ag>>9)+ao~(am&(an~ao))+ap+S[E]+t[a8-1]+i(aq/2^32)aq=aq%2^32;aj=ai;ap=ao;ai=ah;ao=an;ah=ag;an=am;ag=aq+af%2^32;am=ar+al+i(ag/2^32)ag=0|(ag+2^31)%2^32-2^31;af=ae;al=ak;ae=ab;ak=ac;ab=a9;ac=aa;aq=aq+af&ae~(ab&(af~ae))%2^32+ab>>28~(ac<<4)~(ab<<30)~(ac>>2)~(ab<<25)~(ac>>7)%2^32;aa=ar+al&ak~(ac&(al~ak))+ac>>28~(ab<<4)~(ac<<30)~(ab>>2)~(ac<<25)~(ab>>7)+i(aq/2^32)a9=0|(aq+2^31)%2^32-2^31 end;a9=T%2^32+a9%2^32;a0=a0+aa+i(a9/2^32)T=0|(a9+2^31)%2^32-2^31;a9=U%2^32+ab%2^32;a1=a1+ac+i(a9/2^32)U=0|(a9+2^31)%2^32-2^31;a9=V%2^32+ae%2^32;a2=a2+ak+i(a9/2^32)V=0|(a9+2^31)%2^32-2^31;a9=W%2^32+af%2^32;a3=a3+al+i(a9/2^32)W=0|(a9+2^31)%2^32-2^31;a9=X%2^32+ag%2^32;a4=a4+am+i(a9/2^32)X=0|(a9+2^31)%2^32-2^31;a9=Y%2^32+ah%2^32;a5=a5+an+i(a9/2^32)Y=0|(a9+2^31)%2^32-2^31;a9=Z%2^32+ai%2^32;a6=a6+ao+i(a9/2^32)Z=0|(a9+2^31)%2^32-2^31;a9=_%2^32+aj%2^32;a7=a7+ap+i(a9/2^32)_=0|(a9+2^31)%2^32-2^31 end;P[1],P[2],P[3],P[4],P[5],P[6],P[7],P[8]=T,U,V,W,X,Y,Z,_;Q[1],Q[2],Q[3],Q[4],Q[5],Q[6],Q[7],Q[8]=a0,a1,a2,a3,a4,a5,a6,a7 end;local function as(p,q,r,s)local t,u,a=n,b,a;local v,w,x,y=p[1],p[2],p[3],p[4]for D=r+1,r+s,64 do t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15],t[16]=h("<i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4",q,D)local F,G,H,I=v,w,x,y;local at=32-7;for E=1,16 do local au=I~(G&(H~I))+F+u[E]+t[E]F=I;I=H;H=G;G=au<<32-at|(au>>at)+G;at=a[at]end;at=32-5;for E=17,32 do local au=H~(I&(G~H))+F+u[E]+t[5*E-4&15+1]F=I;I=H;H=G;G=au<<32-at|(au>>at)+G;at=a[at]end;at=32-4;for E=33,48 do local au=G~H~I+F+u[E]+t[3*E+2&15+1]F=I;I=H;H=G;G=au<<32-at|(au>>at)+G;at=a[at]end;at=32-6;for E=49,64 do local au=H~(G|~I)+F+u[E]+t[E*7-7&15+1]F=I;I=H;H=G;G=au<<32-at|(au>>at)+G;at=a[at]end;v=F+v;w=G+w;x=H+x;y=I+y end;p[1],p[2],p[3],p[4]=v,w,x,y end;local function av(p,q,r,s)local t=n;local v,w,x,y,z=p[1],p[2],p[3],p[4],p[5]for D=r+1,r+s,64 do t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15],t[16]=h(">i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4",q,D)for E=17,80 do local F=t[E-3]~t[E-8]~t[E-14]~t[E-16]t[E]=F<<1~(F>>31)end;local F,G,H,I,J=v,w,x,y,z;for E=1,20 do local N=F<<5~(F>>27)+I~(G&(H~I))+0x5A827999+t[E]+J;J=I;I=H;H=G<<30~(G>>2)G=F;F=N end;for E=21,40 do local N=F<<5~(F>>27)+G~H~I+0x6ED9EBA1+t[E]+J;J=I;I=H;H=G<<30~(G>>2)G=F;F=N end;for E=41,60 do local N=F<<5~(F>>27)+G~H&I~(G&H)+0x8F1BBCDC+t[E]+J;J=I;I=H;H=G<<30~(G>>2)G=F;F=N end;for E=61,80 do local N=F<<5~(F>>27)+G~H~I+0xCA62C1D6+t[E]+J;J=I;I=H;H=G<<30~(G>>2)G=F;F=N end;v=F+v;w=G+w;x=H+x;y=I+y;z=J+z end;p[1],p[2],p[3],p[4],p[5]=v,w,x,y,z end;local aw=e("i4i4")local function ax(ay,az,q,r,s,aA)local aB,aC=f,g;local aD=aA/8;local aE=aw[aD]for D=r+1,r+s,aA do local aF={h(aE,q,D)}for E=1,aD do ay[E]=ay[E]~aF[2*E-1]az[E]=az[E]~aF[2*E]end;local aG,aH,aI,aJ,aK,aL,aM,aN,aO,aP,aQ,aR,aS,aT,aU,aV,aW,aX,aY,aZ,a_,b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,ba,bb,bc,bd,be,bf,bg,bh,bi,bj,bk,bl,bm,bn,bo,bp,bq,br,bs=ay[1],az[1],ay[2],az[2],ay[3],az[3],ay[4],az[4],ay[5],az[5],ay[6],az[6],ay[7],az[7],ay[8],az[8],ay[9],az[9],ay[10],az[10],ay[11],az[11],ay[12],az[12],ay[13],az[13],ay[14],az[14],ay[15],az[15],ay[16],az[16],ay[17],az[17],ay[18],az[18],ay[19],az[19],ay[20],az[20],ay[21],az[21],ay[22],az[22],ay[23],az[23],ay[24],az[24],ay[25],az[25]for bt=1,24 do local bu=aG~aQ~a_~b9~bj;local bv=aH~aR~b0~ba~bk;local bw=aI~aS~b1~bb~bl;local bx=aJ~aT~b2~bc~bm;local by=aK~aU~b3~bd~bn;local bz=aL~aV~b4~be~bo;local bA=aM~aW~b5~bf~bp;local bB=aN~aX~b6~bg~bq;local bC=aO~aY~b7~bh~br;local bD=aP~aZ~b8~bi~bs;local bE=bu~(by<<1)~(bz>>31)local bF=bv~(bz<<1)~(by>>31)local bG=bE~aI;local bH=bF~aJ;local bI=bE~aS;local bJ=bF~aT;local bK=bE~b1;local bL=bF~b2;local bM=bE~bb;local bN=bF~bc;local bO=bE~bl;local bP=bF~bm;aI=bI>>20~(bJ<<12)aJ=bJ>>20~(bI<<12)aS=bM>>19~(bN<<13)aT=bN>>19~(bM<<13)b1=bG<<1~(bH>>31)b2=bH<<1~(bG>>31)bb=bK<<10~(bL>>22)bc=bL<<10~(bK>>22)bl=bO<<2~(bP>>30)bm=bP<<2~(bO>>30)bE=bw~(bA<<1)~(bB>>31)bF=bx~(bB<<1)~(bA>>31)bG=bE~aK;bH=bF~aL;bI=bE~aU;bJ=bF~aV;bK=bE~b3;bL=bF~b4;bM=bE~bd;bN=bF~be;bO=bE~bn;bP=bF~bo;aK=bK>>21~(bL<<11)aL=bL>>21~(bK<<11)aU=bO>>3~(bP<<29)aV=bP>>3~(bO<<29)b3=bI<<6~(bJ>>26)b4=bJ<<6~(bI>>26)bd=bM<<15~(bN>>17)be=bN<<15~(bM>>17)bn=bG>>2~(bH<<30)bo=bH>>2~(bG<<30)bE=by~(bC<<1)~(bD>>31)bF=bz~(bD<<1)~(bC>>31)bG=bE~aM;bH=bF~aN;bI=bE~aW;bJ=bF~aX;bK=bE~b5;bL=bF~b6;bM=bE~bf;bN=bF~bg;bO=bE~bp;bP=bF~bq;aM=bM<<21~(bN>>11)aN=bN<<21~(bM>>11)aW=bG<<28~(bH>>4)aX=bH<<28~(bG>>4)b5=bK<<25~(bL>>7)b6=bL<<25~(bK>>7)bf=bO>>8~(bP<<24)bg=bP>>8~(bO<<24)bp=bI>>9~(bJ<<23)bq=bJ>>9~(bI<<23)bE=bA~(bu<<1)~(bv>>31)bF=bB~(bv<<1)~(bu>>31)bG=bE~aO;bH=bF~aP;bI=bE~aY;bJ=bF~aZ;bK=bE~b7;bL=bF~b8;bM=bE~bh;bN=bF~bi;bO=bE~br;bP=bF~bs;aO=bO<<14~(bP>>18)aP=bP<<14~(bO>>18)aY=bI<<20~(bJ>>12)aZ=bJ<<20~(bI>>12)b7=bM<<8~(bN>>24)b8=bN<<8~(bM>>24)bh=bG<<27~(bH>>5)bi=bH<<27~(bG>>5)br=bK>>25~(bL<<7)bs=bL>>25~(bK<<7)bE=bC~(bw<<1)~(bx>>31)bF=bD~(bx<<1)~(bw>>31)bI=bE~aQ;bJ=bF~aR;bK=bE~a_;bL=bF~b0;bM=bE~b9;bN=bF~ba;bO=bE~bj;bP=bF~bk;aQ=bK<<3~(bL>>29)aR=bL<<3~(bK>>29)a_=bO<<18~(bP>>14)b0=bP<<18~(bO>>14)b9=bI>>28~(bJ<<4)ba=bJ>>28~(bI<<4)bj=bM>>23~(bN<<9)bk=bN>>23~(bM<<9)aG=bE~aG;aH=bF~aH;aG,aI,aK,aM,aO=aG~(~aI&aK),aI~(~aK&aM),aK~(~aM&aO),aM~(~aO&aG),aO~(~aG&aI)aH,aJ,aL,aN,aP=aH~(~aJ&aL),aJ~(~aL&aN),aL~(~aN&aP),aN~(~aP&aH),aP~(~aH&aJ)aQ,aS,aU,aW,aY=aW~(~aY&aQ),aY~(~aQ&aS),aQ~(~aS&aU),aS~(~aU&aW),aU~(~aW&aY)aR,aT,aV,aX,aZ=aX~(~aZ&aR),aZ~(~aR&aT),aR~(~aT&aV),aT~(~aV&aX),aV~(~aX&aZ)a_,b1,b3,b5,b7=b1~(~b3&b5),b3~(~b5&b7),b5~(~b7&a_),b7~(~a_&b1),a_~(~b1&b3)b0,b2,b4,b6,b8=b2~(~b4&b6),b4~(~b6&b8),b6~(~b8&b0),b8~(~b0&b2),b0~(~b2&b4)b9,bb,bd,bf,bh=bh~(~b9&bb),b9~(~bb&bd),bb~(~bd&bf),bd~(~bf&bh),bf~(~bh&b9)ba,bc,be,bg,bi=bi~(~ba&bc),ba~(~bc&be),bc~(~be&bg),be~(~bg&bi),bg~(~bi&ba)bj,bl,bn,bp,br=bn~(~bp&br),bp~(~br&bj),br~(~bj&bl),bj~(~bl&bn),bl~(~bn&bp)bk,bm,bo,bq,bs=bo~(~bq&bs),bq~(~bs&bk),bs~(~bk&bm),bk~(~bm&bo),bm~(~bo&bq)aG=aG~aB[bt]aH=aH~aC[bt]end;ay[1]=aG;az[1]=aH;ay[2]=aI;az[2]=aJ;ay[3]=aK;az[3]=aL;ay[4]=aM;az[4]=aN;ay[5]=aO;az[5]=aP;ay[6]=aQ;az[6]=aR;ay[7]=aS;az[7]=aT;ay[8]=aU;az[8]=aV;ay[9]=aW;az[9]=aX;ay[10]=aY;az[10]=aZ;ay[11]=a_;az[11]=b0;ay[12]=b1;az[12]=b2;ay[13]=b3;az[13]=b4;ay[14]=b5;az[14]=b6;ay[15]=b7;az[15]=b8;ay[16]=b9;az[16]=ba;ay[17]=bb;az[17]=bc;ay[18]=bd;az[18]=be;ay[19]=bf;az[19]=bg;ay[20]=bh;az[20]=bi;ay[21]=bj;az[21]=bk;ay[22]=bl;az[22]=bm;ay[23]=bn;az[23]=bo;ay[24]=bp;az[24]=bq;ay[25]=br;az[25]=bs end end;return j,l,o,O,as,av,ax]](md5_next_shift, md5_K, sha2_K_lo, sha2_K_hi, build_keccak_format, sha3_RC_lo, sha3_RC_hi) | |
end | |
if branch == "LIB32" or branch == "EMUL" then | |
-- implementation for Lua 5.1/5.2 (with or without bitwise library available) | |
function sha256_feed_64(H, str, offs, size) | |
-- offs >= 0, size >= 0, size is multiple of 64 | |
local W, K = common_W, sha2_K_hi | |
local h1, h2, h3, h4, h5, h6, h7, h8 = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8] | |
for pos = offs, offs + size - 1, 64 do | |
for j = 1, 16 do | |
pos = pos + 4 | |
local a, b, c, d = byte(str, pos - 3, pos) | |
W[j] = ((a * 256 + b) * 256 + c) * 256 + d | |
end | |
for j = 17, 64 do | |
local a, b = W[j-15], W[j-2] | |
W[j] = XOR(ROR(a, 7), ROL(a, 14), SHR(a, 3)) + XOR(ROL(b, 15), ROL(b, 13), SHR(b, 10)) + W[j-7] + W[j-16] | |
end | |
local a, b, c, d, e, f, g, h = h1, h2, h3, h4, h5, h6, h7, h8 | |
for j = 1, 64 do | |
local z = XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + AND(e, f) + AND(-1-e, g) + h + K[j] + W[j] | |
h = g | |
g = f | |
f = e | |
e = z + d | |
d = c | |
c = b | |
b = a | |
a = z + AND(d, c) + AND(a, XOR(d, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) | |
end | |
h1, h2, h3, h4 = (a + h1) % 4294967296, (b + h2) % 4294967296, (c + h3) % 4294967296, (d + h4) % 4294967296 | |
h5, h6, h7, h8 = (e + h5) % 4294967296, (f + h6) % 4294967296, (g + h7) % 4294967296, (h + h8) % 4294967296 | |
end | |
H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8] = h1, h2, h3, h4, h5, h6, h7, h8 | |
end | |
function sha512_feed_128(H_lo, H_hi, str, offs, size) | |
-- offs >= 0, size >= 0, size is multiple of 128 | |
-- W1_hi, W1_lo, W2_hi, W2_lo, ... Wk_hi = W[2*k-1], Wk_lo = W[2*k] | |
local W, K_lo, K_hi = common_W, sha2_K_lo, sha2_K_hi | |
local h1_lo, h2_lo, h3_lo, h4_lo, h5_lo, h6_lo, h7_lo, h8_lo = H_lo[1], H_lo[2], H_lo[3], H_lo[4], H_lo[5], H_lo[6], H_lo[7], H_lo[8] | |
local h1_hi, h2_hi, h3_hi, h4_hi, h5_hi, h6_hi, h7_hi, h8_hi = H_hi[1], H_hi[2], H_hi[3], H_hi[4], H_hi[5], H_hi[6], H_hi[7], H_hi[8] | |
for pos = offs, offs + size - 1, 128 do | |
for j = 1, 16*2 do | |
pos = pos + 4 | |
local a, b, c, d = byte(str, pos - 3, pos) | |
W[j] = ((a * 256 + b) * 256 + c) * 256 + d | |
end | |
for jj = 17*2, 80*2, 2 do | |
local a_lo, a_hi, b_lo, b_hi = W[jj-30], W[jj-31], W[jj-4], W[jj-5] | |
local tmp1 = XOR(SHR(a_lo, 1) + SHL(a_hi, 31), SHR(a_lo, 8) + SHL(a_hi, 24), SHR(a_lo, 7) + SHL(a_hi, 25)) % 4294967296 + XOR(SHR(b_lo, 19) + SHL(b_hi, 13), SHL(b_lo, 3) + SHR(b_hi, 29), SHR(b_lo, 6) + SHL(b_hi, 26)) % 4294967296 + W[jj-14] + W[jj-32] | |
local tmp2 = tmp1 % 4294967296 | |
W[jj-1] = XOR(SHR(a_hi, 1) + SHL(a_lo, 31), SHR(a_hi, 8) + SHL(a_lo, 24), SHR(a_hi, 7)) + XOR(SHR(b_hi, 19) + SHL(b_lo, 13), SHL(b_hi, 3) + SHR(b_lo, 29), SHR(b_hi, 6)) + W[jj-15] + W[jj-33] + (tmp1 - tmp2) / 4294967296 | |
W[jj] = tmp2 | |
end | |
local a_lo, b_lo, c_lo, d_lo, e_lo, f_lo, g_lo, h_lo = h1_lo, h2_lo, h3_lo, h4_lo, h5_lo, h6_lo, h7_lo, h8_lo | |
local a_hi, b_hi, c_hi, d_hi, e_hi, f_hi, g_hi, h_hi = h1_hi, h2_hi, h3_hi, h4_hi, h5_hi, h6_hi, h7_hi, h8_hi | |
for j = 1, 80 do | |
local jj = 2*j | |
local tmp1 = XOR(SHR(e_lo, 14) + SHL(e_hi, 18), SHR(e_lo, 18) + SHL(e_hi, 14), SHL(e_lo, 23) + SHR(e_hi, 9)) % 4294967296 + (AND(e_lo, f_lo) + AND(-1-e_lo, g_lo)) % 4294967296 + h_lo + K_lo[j] + W[jj] | |
local z_lo = tmp1 % 4294967296 | |
local z_hi = XOR(SHR(e_hi, 14) + SHL(e_lo, 18), SHR(e_hi, 18) + SHL(e_lo, 14), SHL(e_hi, 23) + SHR(e_lo, 9)) + AND(e_hi, f_hi) + AND(-1-e_hi, g_hi) + h_hi + K_hi[j] + W[jj-1] + (tmp1 - z_lo) / 4294967296 | |
h_lo = g_lo | |
h_hi = g_hi | |
g_lo = f_lo | |
g_hi = f_hi | |
f_lo = e_lo | |
f_hi = e_hi | |
tmp1 = z_lo + d_lo | |
e_lo = tmp1 % 4294967296 | |
e_hi = z_hi + d_hi + (tmp1 - e_lo) / 4294967296 | |
d_lo = c_lo | |
d_hi = c_hi | |
c_lo = b_lo | |
c_hi = b_hi | |
b_lo = a_lo | |
b_hi = a_hi | |
tmp1 = z_lo + (AND(d_lo, c_lo) + AND(b_lo, XOR(d_lo, c_lo))) % 4294967296 + XOR(SHR(b_lo, 28) + SHL(b_hi, 4), SHL(b_lo, 30) + SHR(b_hi, 2), SHL(b_lo, 25) + SHR(b_hi, 7)) % 4294967296 | |
a_lo = tmp1 % 4294967296 | |
a_hi = z_hi + (AND(d_hi, c_hi) + AND(b_hi, XOR(d_hi, c_hi))) + XOR(SHR(b_hi, 28) + SHL(b_lo, 4), SHL(b_hi, 30) + SHR(b_lo, 2), SHL(b_hi, 25) + SHR(b_lo, 7)) + (tmp1 - a_lo) / 4294967296 | |
end | |
a_lo = h1_lo + a_lo | |
h1_lo = a_lo % 4294967296 | |
h1_hi = (h1_hi + a_hi + (a_lo - h1_lo) / 4294967296) % 4294967296 | |
a_lo = h2_lo + b_lo | |
h2_lo = a_lo % 4294967296 | |
h2_hi = (h2_hi + b_hi + (a_lo - h2_lo) / 4294967296) % 4294967296 | |
a_lo = h3_lo + c_lo | |
h3_lo = a_lo % 4294967296 | |
h3_hi = (h3_hi + c_hi + (a_lo - h3_lo) / 4294967296) % 4294967296 | |
a_lo = h4_lo + d_lo | |
h4_lo = a_lo % 4294967296 | |
h4_hi = (h4_hi + d_hi + (a_lo - h4_lo) / 4294967296) % 4294967296 | |
a_lo = h5_lo + e_lo | |
h5_lo = a_lo % 4294967296 | |
h5_hi = (h5_hi + e_hi + (a_lo - h5_lo) / 4294967296) % 4294967296 | |
a_lo = h6_lo + f_lo | |
h6_lo = a_lo % 4294967296 | |
h6_hi = (h6_hi + f_hi + (a_lo - h6_lo) / 4294967296) % 4294967296 | |
a_lo = h7_lo + g_lo | |
h7_lo = a_lo % 4294967296 | |
h7_hi = (h7_hi + g_hi + (a_lo - h7_lo) / 4294967296) % 4294967296 | |
a_lo = h8_lo + h_lo | |
h8_lo = a_lo % 4294967296 | |
h8_hi = (h8_hi + h_hi + (a_lo - h8_lo) / 4294967296) % 4294967296 | |
end | |
H_lo[1], H_lo[2], H_lo[3], H_lo[4], H_lo[5], H_lo[6], H_lo[7], H_lo[8] = h1_lo, h2_lo, h3_lo, h4_lo, h5_lo, h6_lo, h7_lo, h8_lo | |
H_hi[1], H_hi[2], H_hi[3], H_hi[4], H_hi[5], H_hi[6], H_hi[7], H_hi[8] = h1_hi, h2_hi, h3_hi, h4_hi, h5_hi, h6_hi, h7_hi, h8_hi | |
end | |
function md5_feed_64(H, str, offs, size) | |
-- offs >= 0, size >= 0, size is multiple of 64 | |
local W, K, md5_next_shift = common_W, md5_K, md5_next_shift | |
local h1, h2, h3, h4 = H[1], H[2], H[3], H[4] | |
for pos = offs, offs + size - 1, 64 do | |
for j = 1, 16 do | |
pos = pos + 4 | |
local a, b, c, d = byte(str, pos - 3, pos) | |
W[j] = ((d * 256 + c) * 256 + b) * 256 + a | |
end | |
local a, b, c, d = h1, h2, h3, h4 | |
local s = 32-7 | |
for j = 1, 16 do | |
local F = ROR(AND(b, c) + AND(-1-b, d) + a + K[j] + W[j], s) + b | |
s = md5_next_shift[s] | |
a = d | |
d = c | |
c = b | |
b = F | |
end | |
s = 32-5 | |
for j = 17, 32 do | |
local F = ROR(AND(d, b) + AND(-1-d, c) + a + K[j] + W[(5*j-4) % 16 + 1], s) + b | |
s = md5_next_shift[s] | |
a = d | |
d = c | |
c = b | |
b = F | |
end | |
s = 32-4 | |
for j = 33, 48 do | |
local F = ROR(XOR(XOR(b, c), d) + a + K[j] + W[(3*j+2) % 16 + 1], s) + b | |
s = md5_next_shift[s] | |
a = d | |
d = c | |
c = b | |
b = F | |
end | |
s = 32-6 | |
for j = 49, 64 do | |
local F = ROR(XOR(c, OR(b, -1-d)) + a + K[j] + W[(j*7-7) % 16 + 1], s) + b | |
s = md5_next_shift[s] | |
a = d | |
d = c | |
c = b | |
b = F | |
end | |
h1 = (a + h1) % 4294967296 | |
h2 = (b + h2) % 4294967296 | |
h3 = (c + h3) % 4294967296 | |
h4 = (d + h4) % 4294967296 | |
end | |
H[1], H[2], H[3], H[4] = h1, h2, h3, h4 | |
end | |
function sha1_feed_64(H, str, offs, size) | |
-- offs >= 0, size >= 0, size is multiple of 64 | |
local W = common_W | |
local h1, h2, h3, h4, h5 = H[1], H[2], H[3], H[4], H[5] | |
for pos = offs, offs + size - 1, 64 do | |
for j = 1, 16 do | |
pos = pos + 4 | |
local a, b, c, d = byte(str, pos - 3, pos) | |
W[j] = ((a * 256 + b) * 256 + c) * 256 + d | |
end | |
for j = 17, 80 do | |
W[j] = ROL(XOR(W[j-3], W[j-8], W[j-14], W[j-16]), 1) | |
end | |
local a, b, c, d, e = h1, h2, h3, h4, h5 | |
for j = 1, 20 do | |
local z = ROL(a, 5) + AND(b, c) + AND(-1-b, d) + 0x5A827999 + W[j] + e -- constant = floor(2^30 * sqrt(2)) | |
e = d | |
d = c | |
c = ROR(b, 2) | |
b = a | |
a = z | |
end | |
for j = 21, 40 do | |
local z = ROL(a, 5) + XOR(b, c, d) + 0x6ED9EBA1 + W[j] + e -- 2^30 * sqrt(3) | |
e = d | |
d = c | |
c = ROR(b, 2) | |
b = a | |
a = z | |
end | |
for j = 41, 60 do | |
local z = ROL(a, 5) + AND(d, c) + AND(b, XOR(d, c)) + 0x8F1BBCDC + W[j] + e -- 2^30 * sqrt(5) | |
e = d | |
d = c | |
c = ROR(b, 2) | |
b = a | |
a = z | |
end | |
for j = 61, 80 do | |
local z = ROL(a, 5) + XOR(b, c, d) + 0xCA62C1D6 + W[j] + e -- 2^30 * sqrt(10) | |
e = d | |
d = c | |
c = ROR(b, 2) | |
b = a | |
a = z | |
end | |
h1 = (a + h1) % 4294967296 | |
h2 = (b + h2) % 4294967296 | |
h3 = (c + h3) % 4294967296 | |
h4 = (d + h4) % 4294967296 | |
h5 = (e + h5) % 4294967296 | |
end | |
H[1], H[2], H[3], H[4], H[5] = h1, h2, h3, h4, h5 | |
end | |
function keccak_feed(lanes_lo, lanes_hi, str, offs, size, block_size_in_bytes) | |
-- This is an example of a Lua function having 79 local variables :-) | |
-- offs >= 0, size >= 0, size is multiple of block_size_in_bytes, block_size_in_bytes is positive multiple of 8 | |
local RC_lo, RC_hi = sha3_RC_lo, sha3_RC_hi | |
local qwords_qty = block_size_in_bytes / 8 | |
for pos = offs, offs + size - 1, block_size_in_bytes do | |
for j = 1, qwords_qty do | |
local a, b, c, d = byte(str, pos + 1, pos + 4) | |
lanes_lo[j] = XOR(lanes_lo[j], ((d * 256 + c) * 256 + b) * 256 + a) | |
pos = pos + 8 | |
a, b, c, d = byte(str, pos - 3, pos) | |
lanes_hi[j] = XOR(lanes_hi[j], ((d * 256 + c) * 256 + b) * 256 + a) | |
end | |
local L01_lo, L01_hi, L02_lo, L02_hi, L03_lo, L03_hi, L04_lo, L04_hi, L05_lo, L05_hi, L06_lo, L06_hi, L07_lo, L07_hi, L08_lo, L08_hi, | |
L09_lo, L09_hi, L10_lo, L10_hi, L11_lo, L11_hi, L12_lo, L12_hi, L13_lo, L13_hi, L14_lo, L14_hi, L15_lo, L15_hi, L16_lo, L16_hi, | |
L17_lo, L17_hi, L18_lo, L18_hi, L19_lo, L19_hi, L20_lo, L20_hi, L21_lo, L21_hi, L22_lo, L22_hi, L23_lo, L23_hi, L24_lo, L24_hi, L25_lo, L25_hi = | |
lanes_lo[1], lanes_hi[1], lanes_lo[2], lanes_hi[2], lanes_lo[3], lanes_hi[3], lanes_lo[4], lanes_hi[4], lanes_lo[5], lanes_hi[5], | |
lanes_lo[6], lanes_hi[6], lanes_lo[7], lanes_hi[7], lanes_lo[8], lanes_hi[8], lanes_lo[9], lanes_hi[9], lanes_lo[10], lanes_hi[10], | |
lanes_lo[11], lanes_hi[11], lanes_lo[12], lanes_hi[12], lanes_lo[13], lanes_hi[13], lanes_lo[14], lanes_hi[14], lanes_lo[15], lanes_hi[15], | |
lanes_lo[16], lanes_hi[16], lanes_lo[17], lanes_hi[17], lanes_lo[18], lanes_hi[18], lanes_lo[19], lanes_hi[19], lanes_lo[20], lanes_hi[20], | |
lanes_lo[21], lanes_hi[21], lanes_lo[22], lanes_hi[22], lanes_lo[23], lanes_hi[23], lanes_lo[24], lanes_hi[24], lanes_lo[25], lanes_hi[25] | |
for round_idx = 1, 24 do | |
local C1_lo = XOR(L01_lo, L06_lo, L11_lo, L16_lo, L21_lo) | |
local C1_hi = XOR(L01_hi, L06_hi, L11_hi, L16_hi, L21_hi) | |
local C2_lo = XOR(L02_lo, L07_lo, L12_lo, L17_lo, L22_lo) | |
local C2_hi = XOR(L02_hi, L07_hi, L12_hi, L17_hi, L22_hi) | |
local C3_lo = XOR(L03_lo, L08_lo, L13_lo, L18_lo, L23_lo) | |
local C3_hi = XOR(L03_hi, L08_hi, L13_hi, L18_hi, L23_hi) | |
local C4_lo = XOR(L04_lo, L09_lo, L14_lo, L19_lo, L24_lo) | |
local C4_hi = XOR(L04_hi, L09_hi, L14_hi, L19_hi, L24_hi) | |
local C5_lo = XOR(L05_lo, L10_lo, L15_lo, L20_lo, L25_lo) | |
local C5_hi = XOR(L05_hi, L10_hi, L15_hi, L20_hi, L25_hi) | |
local D_lo = XOR(C1_lo, C3_lo * 2 + (C3_hi % 2^32 - C3_hi % 2^31) / 2^31) | |
local D_hi = XOR(C1_hi, C3_hi * 2 + (C3_lo % 2^32 - C3_lo % 2^31) / 2^31) | |
local T0_lo = XOR(D_lo, L02_lo) | |
local T0_hi = XOR(D_hi, L02_hi) | |
local T1_lo = XOR(D_lo, L07_lo) | |
local T1_hi = XOR(D_hi, L07_hi) | |
local T2_lo = XOR(D_lo, L12_lo) | |
local T2_hi = XOR(D_hi, L12_hi) | |
local T3_lo = XOR(D_lo, L17_lo) | |
local T3_hi = XOR(D_hi, L17_hi) | |
local T4_lo = XOR(D_lo, L22_lo) | |
local T4_hi = XOR(D_hi, L22_hi) | |
L02_lo = (T1_lo % 2^32 - T1_lo % 2^20) / 2^20 + T1_hi * 2^12 | |
L02_hi = (T1_hi % 2^32 - T1_hi % 2^20) / 2^20 + T1_lo * 2^12 | |
L07_lo = (T3_lo % 2^32 - T3_lo % 2^19) / 2^19 + T3_hi * 2^13 | |
L07_hi = (T3_hi % 2^32 - T3_hi % 2^19) / 2^19 + T3_lo * 2^13 | |
L12_lo = T0_lo * 2 + (T0_hi % 2^32 - T0_hi % 2^31) / 2^31 | |
L12_hi = T0_hi * 2 + (T0_lo % 2^32 - T0_lo % 2^31) / 2^31 | |
L17_lo = T2_lo * 2^10 + (T2_hi % 2^32 - T2_hi % 2^22) / 2^22 | |
L17_hi = T2_hi * 2^10 + (T2_lo % 2^32 - T2_lo % 2^22) / 2^22 | |
L22_lo = T4_lo * 2^2 + (T4_hi % 2^32 - T4_hi % 2^30) / 2^30 | |
L22_hi = T4_hi * 2^2 + (T4_lo % 2^32 - T4_lo % 2^30) / 2^30 | |
D_lo = XOR(C2_lo, C4_lo * 2 + (C4_hi % 2^32 - C4_hi % 2^31) / 2^31) | |
D_hi = XOR(C2_hi, C4_hi * 2 + (C4_lo % 2^32 - C4_lo % 2^31) / 2^31) | |
T0_lo = XOR(D_lo, L03_lo) | |
T0_hi = XOR(D_hi, L03_hi) | |
T1_lo = XOR(D_lo, L08_lo) | |
T1_hi = XOR(D_hi, L08_hi) | |
T2_lo = XOR(D_lo, L13_lo) | |
T2_hi = XOR(D_hi, L13_hi) | |
T3_lo = XOR(D_lo, L18_lo) | |
T3_hi = XOR(D_hi, L18_hi) | |
T4_lo = XOR(D_lo, L23_lo) | |
T4_hi = XOR(D_hi, L23_hi) | |
L03_lo = (T2_lo % 2^32 - T2_lo % 2^21) / 2^21 + T2_hi * 2^11 | |
L03_hi = (T2_hi % 2^32 - T2_hi % 2^21) / 2^21 + T2_lo * 2^11 | |
L08_lo = (T4_lo % 2^32 - T4_lo % 2^3) / 2^3 + T4_hi * 2^29 % 2^32 | |
L08_hi = (T4_hi % 2^32 - T4_hi % 2^3) / 2^3 + T4_lo * 2^29 % 2^32 | |
L13_lo = T1_lo * 2^6 + (T1_hi % 2^32 - T1_hi % 2^26) / 2^26 | |
L13_hi = T1_hi * 2^6 + (T1_lo % 2^32 - T1_lo % 2^26) / 2^26 | |
L18_lo = T3_lo * 2^15 + (T3_hi % 2^32 - T3_hi % 2^17) / 2^17 | |
L18_hi = T3_hi * 2^15 + (T3_lo % 2^32 - T3_lo % 2^17) / 2^17 | |
L23_lo = (T0_lo % 2^32 - T0_lo % 2^2) / 2^2 + T0_hi * 2^30 % 2^32 | |
L23_hi = (T0_hi % 2^32 - T0_hi % 2^2) / 2^2 + T0_lo * 2^30 % 2^32 | |
D_lo = XOR(C3_lo, C5_lo * 2 + (C5_hi % 2^32 - C5_hi % 2^31) / 2^31) | |
D_hi = XOR(C3_hi, C5_hi * 2 + (C5_lo % 2^32 - C5_lo % 2^31) / 2^31) | |
T0_lo = XOR(D_lo, L04_lo) | |
T0_hi = XOR(D_hi, L04_hi) | |
T1_lo = XOR(D_lo, L09_lo) | |
T1_hi = XOR(D_hi, L09_hi) | |
T2_lo = XOR(D_lo, L14_lo) | |
T2_hi = XOR(D_hi, L14_hi) | |
T3_lo = XOR(D_lo, L19_lo) | |
T3_hi = XOR(D_hi, L19_hi) | |
T4_lo = XOR(D_lo, L24_lo) | |
T4_hi = XOR(D_hi, L24_hi) | |
L04_lo = T3_lo * 2^21 % 2^32 + (T3_hi % 2^32 - T3_hi % 2^11) / 2^11 | |
L04_hi = T3_hi * 2^21 % 2^32 + (T3_lo % 2^32 - T3_lo % 2^11) / 2^11 | |
L09_lo = T0_lo * 2^28 % 2^32 + (T0_hi % 2^32 - T0_hi % 2^4) / 2^4 | |
L09_hi = T0_hi * 2^28 % 2^32 + (T0_lo % 2^32 - T0_lo % 2^4) / 2^4 | |
L14_lo = T2_lo * 2^25 % 2^32 + (T2_hi % 2^32 - T2_hi % 2^7) / 2^7 | |
L14_hi = T2_hi * 2^25 % 2^32 + (T2_lo % 2^32 - T2_lo % 2^7) / 2^7 | |
L19_lo = (T4_lo % 2^32 - T4_lo % 2^8) / 2^8 + T4_hi * 2^24 % 2^32 | |
L19_hi = (T4_hi % 2^32 - T4_hi % 2^8) / 2^8 + T4_lo * 2^24 % 2^32 | |
L24_lo = (T1_lo % 2^32 - T1_lo % 2^9) / 2^9 + T1_hi * 2^23 % 2^32 | |
L24_hi = (T1_hi % 2^32 - T1_hi % 2^9) / 2^9 + T1_lo * 2^23 % 2^32 | |
D_lo = XOR(C4_lo, C1_lo * 2 + (C1_hi % 2^32 - C1_hi % 2^31) / 2^31) | |
D_hi = XOR(C4_hi, C1_hi * 2 + (C1_lo % 2^32 - C1_lo % 2^31) / 2^31) | |
T0_lo = XOR(D_lo, L05_lo) | |
T0_hi = XOR(D_hi, L05_hi) | |
T1_lo = XOR(D_lo, L10_lo) | |
T1_hi = XOR(D_hi, L10_hi) | |
T2_lo = XOR(D_lo, L15_lo) | |
T2_hi = XOR(D_hi, L15_hi) | |
T3_lo = XOR(D_lo, L20_lo) | |
T3_hi = XOR(D_hi, L20_hi) | |
T4_lo = XOR(D_lo, L25_lo) | |
T4_hi = XOR(D_hi, L25_hi) | |
L05_lo = T4_lo * 2^14 + (T4_hi % 2^32 - T4_hi % 2^18) / 2^18 | |
L05_hi = T4_hi * 2^14 + (T4_lo % 2^32 - T4_lo % 2^18) / 2^18 | |
L10_lo = T1_lo * 2^20 % 2^32 + (T1_hi % 2^32 - T1_hi % 2^12) / 2^12 | |
L10_hi = T1_hi * 2^20 % 2^32 + (T1_lo % 2^32 - T1_lo % 2^12) / 2^12 | |
L15_lo = T3_lo * 2^8 + (T3_hi % 2^32 - T3_hi % 2^24) / 2^24 | |
L15_hi = T3_hi * 2^8 + (T3_lo % 2^32 - T3_lo % 2^24) / 2^24 | |
L20_lo = T0_lo * 2^27 % 2^32 + (T0_hi % 2^32 - T0_hi % 2^5) / 2^5 | |
L20_hi = T0_hi * 2^27 % 2^32 + (T0_lo % 2^32 - T0_lo % 2^5) / 2^5 | |
L25_lo = (T2_lo % 2^32 - T2_lo % 2^25) / 2^25 + T2_hi * 2^7 | |
L25_hi = (T2_hi % 2^32 - T2_hi % 2^25) / 2^25 + T2_lo * 2^7 | |
D_lo = XOR(C5_lo, C2_lo * 2 + (C2_hi % 2^32 - C2_hi % 2^31) / 2^31) | |
D_hi = XOR(C5_hi, C2_hi * 2 + (C2_lo % 2^32 - C2_lo % 2^31) / 2^31) | |
T1_lo = XOR(D_lo, L06_lo) | |
T1_hi = XOR(D_hi, L06_hi) | |
T2_lo = XOR(D_lo, L11_lo) | |
T2_hi = XOR(D_hi, L11_hi) | |
T3_lo = XOR(D_lo, L16_lo) | |
T3_hi = XOR(D_hi, L16_hi) | |
T4_lo = XOR(D_lo, L21_lo) | |
T4_hi = XOR(D_hi, L21_hi) | |
L06_lo = T2_lo * 2^3 + (T2_hi % 2^32 - T2_hi % 2^29) / 2^29 | |
L06_hi = T2_hi * 2^3 + (T2_lo % 2^32 - T2_lo % 2^29) / 2^29 | |
L11_lo = T4_lo * 2^18 + (T4_hi % 2^32 - T4_hi % 2^14) / 2^14 | |
L11_hi = T4_hi * 2^18 + (T4_lo % 2^32 - T4_lo % 2^14) / 2^14 | |
L16_lo = (T1_lo % 2^32 - T1_lo % 2^28) / 2^28 + T1_hi * 2^4 | |
L16_hi = (T1_hi % 2^32 - T1_hi % 2^28) / 2^28 + T1_lo * 2^4 | |
L21_lo = (T3_lo % 2^32 - T3_lo % 2^23) / 2^23 + T3_hi * 2^9 | |
L21_hi = (T3_hi % 2^32 - T3_hi % 2^23) / 2^23 + T3_lo * 2^9 | |
L01_lo = XOR(D_lo, L01_lo) | |
L01_hi = XOR(D_hi, L01_hi) | |
L01_lo, L02_lo, L03_lo, L04_lo, L05_lo = XOR(L01_lo, AND(-1-L02_lo, L03_lo)), XOR(L02_lo, AND(-1-L03_lo, L04_lo)), XOR(L03_lo, AND(-1-L04_lo, L05_lo)), XOR(L04_lo, AND(-1-L05_lo, L01_lo)), XOR(L05_lo, AND(-1-L01_lo, L02_lo)) | |
L01_hi, L02_hi, L03_hi, L04_hi, L05_hi = XOR(L01_hi, AND(-1-L02_hi, L03_hi)), XOR(L02_hi, AND(-1-L03_hi, L04_hi)), XOR(L03_hi, AND(-1-L04_hi, L05_hi)), XOR(L04_hi, AND(-1-L05_hi, L01_hi)), XOR(L05_hi, AND(-1-L01_hi, L02_hi)) | |
L06_lo, L07_lo, L08_lo, L09_lo, L10_lo = XOR(L09_lo, AND(-1-L10_lo, L06_lo)), XOR(L10_lo, AND(-1-L06_lo, L07_lo)), XOR(L06_lo, AND(-1-L07_lo, L08_lo)), XOR(L07_lo, AND(-1-L08_lo, L09_lo)), XOR(L08_lo, AND(-1-L09_lo, L10_lo)) | |
L06_hi, L07_hi, L08_hi, L09_hi, L10_hi = XOR(L09_hi, AND(-1-L10_hi, L06_hi)), XOR(L10_hi, AND(-1-L06_hi, L07_hi)), XOR(L06_hi, AND(-1-L07_hi, L08_hi)), XOR(L07_hi, AND(-1-L08_hi, L09_hi)), XOR(L08_hi, AND(-1-L09_hi, L10_hi)) | |
L11_lo, L12_lo, L13_lo, L14_lo, L15_lo = XOR(L12_lo, AND(-1-L13_lo, L14_lo)), XOR(L13_lo, AND(-1-L14_lo, L15_lo)), XOR(L14_lo, AND(-1-L15_lo, L11_lo)), XOR(L15_lo, AND(-1-L11_lo, L12_lo)), XOR(L11_lo, AND(-1-L12_lo, L13_lo)) | |
L11_hi, L12_hi, L13_hi, L14_hi, L15_hi = XOR(L12_hi, AND(-1-L13_hi, L14_hi)), XOR(L13_hi, AND(-1-L14_hi, L15_hi)), XOR(L14_hi, AND(-1-L15_hi, L11_hi)), XOR(L15_hi, AND(-1-L11_hi, L12_hi)), XOR(L11_hi, AND(-1-L12_hi, L13_hi)) | |
L16_lo, L17_lo, L18_lo, L19_lo, L20_lo = XOR(L20_lo, AND(-1-L16_lo, L17_lo)), XOR(L16_lo, AND(-1-L17_lo, L18_lo)), XOR(L17_lo, AND(-1-L18_lo, L19_lo)), XOR(L18_lo, AND(-1-L19_lo, L20_lo)), XOR(L19_lo, AND(-1-L20_lo, L16_lo)) | |
L16_hi, L17_hi, L18_hi, L19_hi, L20_hi = XOR(L20_hi, AND(-1-L16_hi, L17_hi)), XOR(L16_hi, AND(-1-L17_hi, L18_hi)), XOR(L17_hi, AND(-1-L18_hi, L19_hi)), XOR(L18_hi, AND(-1-L19_hi, L20_hi)), XOR(L19_hi, AND(-1-L20_hi, L16_hi)) | |
L21_lo, L22_lo, L23_lo, L24_lo, L25_lo = XOR(L23_lo, AND(-1-L24_lo, L25_lo)), XOR(L24_lo, AND(-1-L25_lo, L21_lo)), XOR(L25_lo, AND(-1-L21_lo, L22_lo)), XOR(L21_lo, AND(-1-L22_lo, L23_lo)), XOR(L22_lo, AND(-1-L23_lo, L24_lo)) | |
L21_hi, L22_hi, L23_hi, L24_hi, L25_hi = XOR(L23_hi, AND(-1-L24_hi, L25_hi)), XOR(L24_hi, AND(-1-L25_hi, L21_hi)), XOR(L25_hi, AND(-1-L21_hi, L22_hi)), XOR(L21_hi, AND(-1-L22_hi, L23_hi)), XOR(L22_hi, AND(-1-L23_hi, L24_hi)) | |
L01_lo = XOR(L01_lo, RC_lo[round_idx]) | |
L01_hi = L01_hi + RC_hi[round_idx] -- RC_hi[] is either 0 or 0x80000000, so we could use fast addition instead of slow XOR | |
end | |
lanes_lo[1] = L01_lo | |
lanes_hi[1] = L01_hi | |
lanes_lo[2] = L02_lo | |
lanes_hi[2] = L02_hi | |
lanes_lo[3] = L03_lo | |
lanes_hi[3] = L03_hi | |
lanes_lo[4] = L04_lo | |
lanes_hi[4] = L04_hi | |
lanes_lo[5] = L05_lo | |
lanes_hi[5] = L05_hi | |
lanes_lo[6] = L06_lo | |
lanes_hi[6] = L06_hi | |
lanes_lo[7] = L07_lo | |
lanes_hi[7] = L07_hi | |
lanes_lo[8] = L08_lo | |
lanes_hi[8] = L08_hi | |
lanes_lo[9] = L09_lo | |
lanes_hi[9] = L09_hi | |
lanes_lo[10] = L10_lo | |
lanes_hi[10] = L10_hi | |
lanes_lo[11] = L11_lo | |
lanes_hi[11] = L11_hi | |
lanes_lo[12] = L12_lo | |
lanes_hi[12] = L12_hi | |
lanes_lo[13] = L13_lo | |
lanes_hi[13] = L13_hi | |
lanes_lo[14] = L14_lo | |
lanes_hi[14] = L14_hi | |
lanes_lo[15] = L15_lo | |
lanes_hi[15] = L15_hi | |
lanes_lo[16] = L16_lo | |
lanes_hi[16] = L16_hi | |
lanes_lo[17] = L17_lo | |
lanes_hi[17] = L17_hi | |
lanes_lo[18] = L18_lo | |
lanes_hi[18] = L18_hi | |
lanes_lo[19] = L19_lo | |
lanes_hi[19] = L19_hi | |
lanes_lo[20] = L20_lo | |
lanes_hi[20] = L20_hi | |
lanes_lo[21] = L21_lo | |
lanes_hi[21] = L21_hi | |
lanes_lo[22] = L22_lo | |
lanes_hi[22] = L22_hi | |
lanes_lo[23] = L23_lo | |
lanes_hi[23] = L23_hi | |
lanes_lo[24] = L24_lo | |
lanes_hi[24] = L24_hi | |
lanes_lo[25] = L25_lo | |
lanes_hi[25] = L25_hi | |
end | |
end | |
end | |
-------------------------------------------------------------------------------- | |
-- MAGIC NUMBERS CALCULATOR | |
-------------------------------------------------------------------------------- | |
-- Q: | |
-- Is 53-bit "double" math enough to calculate square roots and cube roots of primes with 64 correct bits after decimal point? | |
-- A: | |
-- Yes, 53-bit "double" arithmetic is enough. | |
-- We could obtain first 40 bits by direct calculation of p^(1/3) and next 40 bits by one step of Newton's method. | |
do | |
local function mul(src1, src2, factor, result_length) | |
-- src1, src2 - long integers (arrays of digits in base 2^24) | |
-- factor - small integer | |
-- returns long integer result (src1 * src2 * factor) and its floating point approximation | |
local result, carry, value, weight = {}, 0.0, 0.0, 1.0 | |
for j = 1, result_length do | |
for k = math_max(1, j + 1 - #src2), math_min(j, #src1) do | |
carry = carry + factor * src1[k] * src2[j + 1 - k] -- "int32" is not enough for multiplication result, that's why "factor" must be of type "double" | |
end | |
local digit = carry % 2^24 | |
result[j] = floor(digit) | |
carry = (carry - digit) / 2^24 | |
value = value + digit * weight | |
weight = weight * 2^24 | |
end | |
return result, value | |
end | |
local idx, step, p, one, sqrt_hi, sqrt_lo = 0, {4, 1, 2, -2, 2}, 4, {1}, sha2_H_hi, sha2_H_lo | |
repeat | |
p = p + step[p % 6] | |
local d = 1 | |
repeat | |
d = d + step[d % 6] | |
if d*d > p then -- next prime number is found | |
local root = p^(1/3) | |
local R = root * 2^40 | |
R = mul({R - R % 1}, one, 1.0, 2) | |
local _, delta = mul(R, mul(R, R, 1.0, 4), -1.0, 4) | |
local hi = R[2] % 65536 * 65536 + floor(R[1] / 256) | |
local lo = R[1] % 256 * 16777216 + floor(delta * (2^-56 / 3) * root / p) | |
if idx < 16 then | |
root = p^(1/2) | |
R = root * 2^40 | |
R = mul({R - R % 1}, one, 1.0, 2) | |
_, delta = mul(R, R, -1.0, 2) | |
local hi = R[2] % 65536 * 65536 + floor(R[1] / 256) | |
local lo = R[1] % 256 * 16777216 + floor(delta * 2^-17 / root) | |
local idx = idx % 8 + 1 | |
sha2_H_ext256[224][idx] = lo | |
sqrt_hi[idx], sqrt_lo[idx] = hi, lo + hi * hi_factor | |
if idx > 7 then | |
sqrt_hi, sqrt_lo = sha2_H_ext512_hi[384], sha2_H_ext512_lo[384] | |
end | |
end | |
idx = idx + 1 | |
sha2_K_hi[idx], sha2_K_lo[idx] = hi, lo % K_lo_modulo + hi * hi_factor | |
break | |
end | |
until p % d == 0 | |
until idx > 79 | |
end | |
-- Calculating IVs for SHA512/224 and SHA512/256 | |
for width = 224, 256, 32 do | |
local H_lo, H_hi = {} | |
if XOR64A5 then | |
for j = 1, 8 do | |
H_lo[j] = XOR64A5(sha2_H_lo[j]) | |
end | |
else | |
H_hi = {} | |
for j = 1, 8 do | |
H_lo[j] = XOR32A5(sha2_H_lo[j]) | |
H_hi[j] = XOR32A5(sha2_H_hi[j]) | |
end | |
end | |
sha512_feed_128(H_lo, H_hi, "SHA-512/"..tostring(width).."\128"..string_rep("\0", 115).."\88", 0, 128) | |
sha2_H_ext512_lo[width] = H_lo | |
sha2_H_ext512_hi[width] = H_hi | |
end | |
-- Constants for MD5 | |
do | |
local sin, abs, modf = math.sin, math.abs, math.modf | |
for idx = 1, 64 do | |
-- we can't use formula floor(abs(sin(idx))*2^32) because its result may be beyond integer range on Lua built with 32-bit integers | |
local hi, lo = modf(abs(sin(idx)) * 2^16) | |
md5_K[idx] = hi * 65536 + floor(lo * 2^16) | |
end | |
end | |
-- Constants for SHA3 | |
do | |
local sh_reg = 29 | |
local function next_bit() | |
local r = sh_reg % 2 | |
sh_reg = XOR_BYTE((sh_reg - r) / 2, 142 * r) | |
return r | |
end | |
for idx = 1, 24 do | |
local lo, m = 0 | |
for _ = 1, 6 do | |
m = m and m * m * 2 or 1 | |
lo = lo + next_bit() * m | |
end | |
local hi = next_bit() * m | |
sha3_RC_hi[idx], sha3_RC_lo[idx] = hi, lo + hi * hi_factor_keccak | |
end | |
end | |
-------------------------------------------------------------------------------- | |
-- MAIN FUNCTIONS | |
-------------------------------------------------------------------------------- | |
local function sha256ext(width, message) | |
-- Create an instance (private objects for current calculation) | |
local H, length, tail = {unpack(sha2_H_ext256[width])}, 0.0, "" | |
local function partial(message_part) | |
if message_part then | |
if tail then | |
length = length + #message_part | |
local offs = 0 | |
if tail ~= "" and #tail + #message_part >= 64 then | |
offs = 64 - #tail | |
sha256_feed_64(H, tail..sub(message_part, 1, offs), 0, 64) | |
tail = "" | |
end | |
local size = #message_part - offs | |
local size_tail = size % 64 | |
sha256_feed_64(H, message_part, offs, size - size_tail) | |
tail = tail..sub(message_part, #message_part + 1 - size_tail) | |
return partial | |
else | |
error("Adding more chunks is not allowed after receiving the result", 2) | |
end | |
else | |
if tail then | |
local final_blocks = {tail, "\128", string_rep("\0", (-9 - length) % 64 + 1)} | |
tail = nil | |
-- Assuming user data length is shorter than (2^53)-9 bytes | |
-- Anyway, it looks very unrealistic that someone would spend more than a year of calculations to process 2^53 bytes of data by using this Lua script :-) | |
-- 2^53 bytes = 2^56 bits, so "bit-counter" fits in 7 bytes | |
length = length * (8 / 256^7) -- convert "byte-counter" to "bit-counter" and move decimal point to the left | |
for j = 4, 10 do | |
length = length % 1 * 256 | |
final_blocks[j] = char(floor(length)) | |
end | |
final_blocks = table_concat(final_blocks) | |
sha256_feed_64(H, final_blocks, 0, #final_blocks) | |
local max_reg = width / 32 | |
for j = 1, max_reg do | |
H[j] = HEX(H[j]) | |
end | |
H = table_concat(H, "", 1, max_reg) | |
end | |
return H | |
end | |
end | |
if message then | |
-- Actually perform calculations and return the SHA256 digest of a message | |
return partial(message)() | |
else | |
-- Return function for chunk-by-chunk loading | |
-- User should feed every chunk of input data as single argument to this function and finally get SHA256 digest by invoking this function without an argument | |
return partial | |
end | |
end | |
local function sha512ext(width, message) | |
-- Create an instance (private objects for current calculation) | |
local length, tail, H_lo, H_hi = 0.0, "", {unpack(sha2_H_ext512_lo[width])}, not HEX64 and {unpack(sha2_H_ext512_hi[width])} | |
local function partial(message_part) | |
if message_part then | |
if tail then | |
length = length + #message_part | |
local offs = 0 | |
if tail ~= "" and #tail + #message_part >= 128 then | |
offs = 128 - #tail | |
sha512_feed_128(H_lo, H_hi, tail..sub(message_part, 1, offs), 0, 128) | |
tail = "" | |
end | |
local size = #message_part - offs | |
local size_tail = size % 128 | |
sha512_feed_128(H_lo, H_hi, message_part, offs, size - size_tail) | |
tail = tail..sub(message_part, #message_part + 1 - size_tail) | |
return partial | |
else | |
error("Adding more chunks is not allowed after receiving the result", 2) | |
end | |
else | |
if tail then | |
local final_blocks = {tail, "\128", string_rep("\0", (-17-length) % 128 + 9)} | |
tail = nil | |
-- Assuming user data length is shorter than (2^53)-17 bytes | |
-- 2^53 bytes = 2^56 bits, so "bit-counter" fits in 7 bytes | |
length = length * (8 / 256^7) -- convert "byte-counter" to "bit-counter" and move floating point to the left | |
for j = 4, 10 do | |
length = length % 1 * 256 | |
final_blocks[j] = char(floor(length)) | |
end | |
final_blocks = table_concat(final_blocks) | |
sha512_feed_128(H_lo, H_hi, final_blocks, 0, #final_blocks) | |
local max_reg = ceil(width / 64) | |
if HEX64 then | |
for j = 1, max_reg do | |
H_lo[j] = HEX64(H_lo[j]) | |
end | |
else | |
for j = 1, max_reg do | |
H_lo[j] = HEX(H_hi[j])..HEX(H_lo[j]) | |
end | |
H_hi = nil | |
end | |
H_lo = sub(table_concat(H_lo, "", 1, max_reg), 1, width / 4) | |
end | |
return H_lo | |
end | |
end | |
if message then | |
-- Actually perform calculations and return the SHA512 digest of a message | |
return partial(message)() | |
else | |
-- Return function for chunk-by-chunk loading | |
-- User should feed every chunk of input data as single argument to this function and finally get SHA512 digest by invoking this function without an argument | |
return partial | |
end | |
end | |
local function md5(message) | |
-- Create an instance (private objects for current calculation) | |
local H, length, tail = {unpack(md5_sha1_H, 1, 4)}, 0.0, "" | |
local function partial(message_part) | |
if message_part then | |
if tail then | |
length = length + #message_part | |
local offs = 0 | |
if tail ~= "" and #tail + #message_part >= 64 then | |
offs = 64 - #tail | |
md5_feed_64(H, tail..sub(message_part, 1, offs), 0, 64) | |
tail = "" | |
end | |
local size = #message_part - offs | |
local size_tail = size % 64 | |
md5_feed_64(H, message_part, offs, size - size_tail) | |
tail = tail..sub(message_part, #message_part + 1 - size_tail) | |
return partial | |
else | |
error("Adding more chunks is not allowed after receiving the result", 2) | |
end | |
else | |
if tail then | |
local final_blocks = {tail, "\128", string_rep("\0", (-9 - length) % 64)} | |
tail = nil | |
length = length * 8 -- convert "byte-counter" to "bit-counter" | |
for j = 4, 11 do | |
local low_byte = length % 256 | |
final_blocks[j] = char(low_byte) | |
length = (length - low_byte) / 256 | |
end | |
final_blocks = table_concat(final_blocks) | |
md5_feed_64(H, final_blocks, 0, #final_blocks) | |
for j = 1, 4 do | |
H[j] = HEX(H[j]) | |
end | |
H = gsub(table_concat(H), "(..)(..)(..)(..)", "%4%3%2%1") | |
end | |
return H | |
end | |
end | |
if message then | |
-- Actually perform calculations and return the MD5 digest of a message | |
return partial(message)() | |
else | |
-- Return function for chunk-by-chunk loading | |
-- User should feed every chunk of input data as single argument to this function and finally get MD5 digest by invoking this function without an argument | |
return partial | |
end | |
end | |
local function sha1(message) | |
-- Create an instance (private objects for current calculation) | |
local H, length, tail = {unpack(md5_sha1_H)}, 0.0, "" | |
local function partial(message_part) | |
if message_part then | |
if tail then | |
length = length + #message_part | |
local offs = 0 | |
if tail ~= "" and #tail + #message_part >= 64 then | |
offs = 64 - #tail | |
sha1_feed_64(H, tail..sub(message_part, 1, offs), 0, 64) | |
tail = "" | |
end | |
local size = #message_part - offs | |
local size_tail = size % 64 | |
sha1_feed_64(H, message_part, offs, size - size_tail) | |
tail = tail..sub(message_part, #message_part + 1 - size_tail) | |
return partial | |
else | |
error("Adding more chunks is not allowed after receiving the result", 2) | |
end | |
else | |
if tail then | |
local final_blocks = {tail, "\128", string_rep("\0", (-9 - length) % 64 + 1)} | |
tail = nil | |
-- Assuming user data length is shorter than (2^53)-9 bytes | |
-- 2^53 bytes = 2^56 bits, so "bit-counter" fits in 7 bytes | |
length = length * (8 / 256^7) -- convert "byte-counter" to "bit-counter" and move decimal point to the left | |
for j = 4, 10 do | |
length = length % 1 * 256 | |
final_blocks[j] = char(floor(length)) | |
end | |
final_blocks = table_concat(final_blocks) | |
sha1_feed_64(H, final_blocks, 0, #final_blocks) | |
for j = 1, 5 do | |
H[j] = HEX(H[j]) | |
end | |
H = table_concat(H) | |
end | |
return H | |
end | |
end | |
if message then | |
-- Actually perform calculations and return the SHA-1 digest of a message | |
return partial(message)() | |
else | |
-- Return function for chunk-by-chunk loading | |
-- User should feed every chunk of input data as single argument to this function and finally get SHA-1 digest by invoking this function without an argument | |
return partial | |
end | |
end | |
local function keccak(block_size_in_bytes, digest_size_in_bytes, is_SHAKE, message) | |
-- "block_size_in_bytes" is multiple of 8 | |
if type(digest_size_in_bytes) ~= "number" then | |
-- arguments in SHAKE are swapped: | |
-- NIST FIPS 202 defines SHAKE(message,num_bits) | |
-- this module defines SHAKE(num_bytes,message) | |
-- it's easy to forget about this swap, hence the check | |
error("Argument 'digest_size_in_bytes' must be a number", 2) | |
end | |
-- Create an instance (private objects for current calculation) | |
local tail, lanes_lo, lanes_hi = "", create_array_of_lanes(), hi_factor_keccak == 0 and create_array_of_lanes() | |
local result | |
--~ pad the input N using the pad function, yielding a padded bit string P with a length divisible by r (such that n = len(P)/r is integer), | |
--~ break P into n consecutive r-bit pieces P0, ..., Pn-1 (last is zero-padded) | |
--~ initialize the state S to a string of b 0 bits. | |
--~ absorb the input into the state: For each block Pi, | |
--~ extend Pi at the end by a string of c 0 bits, yielding one of length b, | |
--~ XOR that with S and | |
--~ apply the block permutation f to the result, yielding a new state S | |
--~ initialize Z to be the empty string | |
--~ while the length of Z is less than d: | |
--~ append the first r bits of S to Z | |
--~ if Z is still less than d bits long, apply f to S, yielding a new state S. | |
--~ truncate Z to d bits | |
local function partial(message_part) | |
if message_part then | |
if tail then | |
local offs = 0 | |
if tail ~= "" and #tail + #message_part >= block_size_in_bytes then | |
offs = block_size_in_bytes - #tail | |
keccak_feed(lanes_lo, lanes_hi, tail..sub(message_part, 1, offs), 0, block_size_in_bytes, block_size_in_bytes) | |
tail = "" | |
end | |
local size = #message_part - offs | |
local size_tail = size % block_size_in_bytes | |
keccak_feed(lanes_lo, lanes_hi, message_part, offs, size - size_tail, block_size_in_bytes) | |
tail = tail..sub(message_part, #message_part + 1 - size_tail) | |
return partial | |
else | |
error("Adding more chunks is not allowed after receiving the result", 2) | |
end | |
else | |
if tail then | |
< |