Files
wnsrc/lua/pac3/libraries/urlobj/crypto.lua

505 lines
15 KiB
Lua
Raw Normal View History

2024-08-04 22:55:00 +03:00
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local crypto = {}
crypto.UInt8BlockSize = 64
crypto.UInt32BlockSize = 16
crypto.KeySize = crypto.UInt32BlockSize
local bit_band = bit.band
local bit_bxor = bit.bxor
local bit_rshift = bit.rshift
local math_ceil = math.ceil
local math_floor = math.floor
local math_random = math.random
local string_byte = string.byte
local string_char = string.char
local string_sub = string.sub
local table_concat = table.concat
-- byteCharacters [i] is faster than string_char (i)
local byteCharacters1 = {}
local byteCharacters2 = {}
local byteCharacters = byteCharacters1
for i = 0, 255 do byteCharacters1 [i] = string_char (i) end
for uint80 = 0, 255 do
for uint81 = 0, 255 do
byteCharacters2 [uint80 + uint81 * 256] = string_char (uint80, uint81)
end
end
function crypto.GenerateKey (seed, length)
length = length or crypto.KeySize
if isstring (seed) then
-- LOL ONLY 32 BITS OF ENTROPY
seed = tonumber (util.CRC (seed))
end
if seed then
math.randomseed (seed)
end
return crypto.GenerateRandomUInt32Array (length)
end
-- Encrypts a string
function crypto.EncryptString (inputString, keyArray)
local inputArray = crypto.StringToUInt32Array (inputString)
inputArray = crypto.PadUInt32Array (inputArray)
local outputArray = {}
outputArray = crypto.GenerateRandomUInt32Array (crypto.UInt32BlockSize, outputArray)
-- I have no idea either
local keyArray = crypto.CloneArray (keyArray)
keyArray = crypto.AppendArray (keyArray, keyArray)
keyArray = crypto.AppendArray (keyArray, keyArray)
keyArray = crypto.AppendArray (keyArray, keyArray)
keyArray = crypto.AppendArray (keyArray, keyArray)
keyArray = crypto.AppendArray (keyArray, keyArray)
keyArray = crypto.AppendArray (keyArray, keyArray)
crypto.XorInt32Arrays (outputArray, 1, keyArray, 1, crypto.UInt32BlockSize, outputArray, 1)
local inputArrayLength = #inputArray
local inputEndIndex = #inputArray
inputEndIndex = inputEndIndex - ((inputArrayLength / crypto.UInt32BlockSize) % 64) * crypto.UInt32BlockSize
local inputIndex = 1
while inputIndex <= inputEndIndex do
crypto.XorInt32Arrays3 (
inputArray, inputIndex,
outputArray, inputIndex,
keyArray, 1,
crypto.UInt32BlockSize * 64,
outputArray, crypto.UInt32BlockSize + inputIndex
)
inputIndex = inputIndex + crypto.UInt32BlockSize * 64
end
-- Remainder
inputEndIndex = #inputArray
while inputIndex <= inputEndIndex do
crypto.XorInt32Arrays3 (
inputArray, inputIndex,
outputArray, inputIndex,
keyArray, 1,
crypto.UInt32BlockSize,
outputArray, crypto.UInt32BlockSize + inputIndex
)
inputIndex = inputIndex + crypto.UInt32BlockSize
end
local outputString = crypto.Int32ArrayToString (outputArray)
return outputString
end
-- Decrypts a string
function crypto.DecryptString (inputString, keyArray)
local inputArray = crypto.StringToUInt32Array (inputString)
local inputIndex = #inputArray - crypto.UInt32BlockSize + 1
while inputIndex > crypto.UInt32BlockSize do
crypto.XorInt32Arrays3 (
inputArray, inputIndex,
inputArray, inputIndex - crypto.UInt32BlockSize,
keyArray, 1,
crypto.UInt32BlockSize,
inputArray, inputIndex
)
inputIndex = inputIndex - crypto.UInt32BlockSize
end
crypto.XorInt32Arrays (inputArray, 1, keyArray, 1, crypto.UInt32BlockSize, inputArray, 1)
inputArray = crypto.UnpadInt32Array (inputArray)
local outputArray = inputArray
local outputString = crypto.Int32ArrayToString (outputArray, crypto.UInt32BlockSize + 1)
return outputString
end
-- Pads an array in place
function crypto.PadUInt8Array (array)
local targetLength = math_ceil (#array / crypto.UInt8BlockSize) * crypto.UInt8BlockSize
if targetLength == #array then
targetLength = targetLength + crypto.UInt8BlockSize
end
array [#array + 1] = 0xFF
for i = #array + 1, targetLength do
array [i] = 0x00
end
array.n = #array
return array
end
-- Pads an array in place
function crypto.PadUInt32Array (array)
if array.n % 4 == 0 then
array [#array + 1] = 0x000000FF
elseif array.n % 4 == 1 then
array [#array] = array [#array] + 0x0000FF00
elseif array.n % 4 == 2 then
array [#array] = array [#array] + 0x00FF0000
elseif array.n % 4 == 3 then
array [#array] = array [#array] + 0xFF000000
end
local targetLength = math_ceil (#array / crypto.UInt32BlockSize) * crypto.UInt32BlockSize
for i = #array + 1, targetLength do
array [i] = 0x00000000
end
array.n = #array * 4
return array
end
-- Unpads an array in place
function crypto.UnpadUInt8Array (array)
for i = #array, 1, -1 do
if array [i] ~= 0x00 then break end
array [i] = nil
end
if array [#array] == 0xFF then
array [#array] = nil
end
array.n = #array
return array
end
-- Unpads an array in place
function crypto.UnpadUInt32Array (array)
return crypto.UnpadInt32Array (array)
end
-- Unpads an array in place
function crypto.UnpadInt32Array (array)
for i = #array, 1, -1 do
if array [i] ~= 0x00000000 then break end
array [i] = nil
end
array.n = #array * 4
if array [#array] < 0 then
array [#array] = array [#array] + 4294967296
end
if array [#array] - 0xFF000000 >= 0 then
array [#array] = array [#array] - 0xFF000000
array.n = array.n - 1
elseif array [#array] - 0x00FF0000 >= 0 then
array [#array] = array [#array] - 0x00FF0000
array.n = array.n - 2
elseif array [#array] - 0x0000FF00 >= 0 then
array [#array] = array [#array] - 0x0000FF00
array.n = array.n - 3
elseif array [#array] - 0x000000FF >= 0 then
array [#array] = nil
array.n = array.n - 4
end
return array
end
-- Array operations
-- Generates a random array of uint8s
function crypto.GenerateRandomUInt8Array (length, out)
out = out or {}
for i = 1, length do
out [#out + 1] = math_random (0, 0xFF)
end
return out
end
-- Generates a random array of uint32s
function crypto.GenerateRandomUInt32Array (length, out)
out = out or {}
for i = 1, length do
out [#out + 1] = math_random (0, 0xFFFFFFFF)
end
return out
end
-- Appends an array in place
function crypto.AppendArray (array, array1)
local array1Length = #array1
for i = 1, array1Length do
array [#array + 1] = array1 [i]
end
return array
end
-- Clones an array
function crypto.CloneArray (array, out)
out = out or {}
for i = 1, #array do
out [i] = array [i]
end
return out
end
-- Truncates an array in place
function crypto.TruncateArray (array, endIndex)
for i = endIndex + 1, #array do
array [i] = nil
end
return array
end
-- Xors an array with another
function crypto.XorArrays (array1, array1StartIndex, array2, array2StartIndex, length, out, outStartIndex)
return crypto.XorArrays2 (array1, array1StartIndex, array2, array2StartIndex, length, out, outStartIndex)
end
function crypto.XorArrays2 (array1, array1StartIndex, array2, array2StartIndex, length, out, outStartIndex)
out = out or {}
array1StartIndex = array1StartIndex or 1
array2StartIndex = array2StartIndex or 1
outStartIndex = outStartIndex or 1
local array2Index = array2StartIndex
local outputIndex = outStartIndex
local array1EndIndex = array1StartIndex + length - 1
for array1Index = array1StartIndex, array1EndIndex do
out [outputIndex] = bit_bxor (array1 [array1Index], array2 [array2Index])
array2Index = array2Index + 1
outputIndex = outputIndex + 1
end
return out
end
function crypto.XorArrays3 (array1, array1StartIndex, array2, array2StartIndex, array3, array3StartIndex, length, out, outStartIndex)
out = out or {}
array1StartIndex = array1StartIndex or 1
array2StartIndex = array2StartIndex or 1
array3StartIndex = array3StartIndex or 1
outStartIndex = outStartIndex or 1
local array2Index = array2StartIndex
local array3Index = array3StartIndex
local outputIndex = outStartIndex
local array1EndIndex = array1StartIndex + length - 1
for array1Index = array1StartIndex, array1EndIndex do
out [outputIndex] = bit_bxor (array1 [array1Index], array2 [array2Index], array3 [array3Index])
array2Index = array2Index + 1
array3Index = array3Index + 1
outputIndex = outputIndex + 1
end
return out
end
-- Xors an array with another
function crypto.XorUInt8Arrays (array1, array1StartIndex, array2, array2StartIndex, length, out, outStartIndex)
return crypto.XorArrays2 (array1, array1StartIndex, array2, array2StartIndex, length, out, outStartIndex)
end
function crypto.XorUInt8Arrays2 (array1, array1StartIndex, array2, array2StartIndex, length, out, outStartIndex)
return crypto.XorArrays2 (array1, array1StartIndex, array2, array2StartIndex, length, out, outStartIndex)
end
function crypto.XorUInt8Arrays3 (array1, array1StartIndex, array2, array2StartIndex, array3, array3StartIndex, length, out, outStartIndex)
return crypto.XorArrays3 (array1, array1StartIndex, array2, array2StartIndex, array3, array3StartIndex, length, out, outStartIndex)
end
-- Xors an array with another
function crypto.XorInt32Arrays (array1, array1StartIndex, array2, array2StartIndex, length, out, outStartIndex)
return crypto.XorArrays2 (array1, array1StartIndex, array2, array2StartIndex, length, out, outStartIndex)
end
function crypto.XorInt32Arrays2 (array1, array1StartIndex, array2, array2StartIndex, length, out, outStartIndex)
return crypto.XorArrays2 (array1, array1StartIndex, array2, array2StartIndex, length, out, outStartIndex)
end
function crypto.XorInt32Arrays3 (array1, array1StartIndex, array2, array2StartIndex, array3, array3StartIndex, length, out, outStartIndex)
return crypto.XorArrays3 (array1, array1StartIndex, array2, array2StartIndex, array3, array3StartIndex, length, out, outStartIndex)
end
-- Converts a string to an array of uint8s
function crypto.StringToUInt8Array (str, out)
out = out or {}
out.n = #str
-- ARE WE FAST YET?
for i = 1, #str, 64 do
out [i + 0], out [i + 1], out [i + 2], out [i + 3],
out [i + 4], out [i + 5], out [i + 6], out [i + 7],
out [i + 8], out [i + 9], out [i + 10], out [i + 11],
out [i + 12], out [i + 13], out [i + 14], out [i + 15],
out [i + 16], out [i + 17], out [i + 18], out [i + 19],
out [i + 20], out [i + 21], out [i + 22], out [i + 23],
out [i + 24], out [i + 25], out [i + 26], out [i + 27],
out [i + 28], out [i + 29], out [i + 30], out [i + 31],
out [i + 32], out [i + 33], out [i + 34], out [i + 35],
out [i + 36], out [i + 37], out [i + 38], out [i + 39],
out [i + 40], out [i + 41], out [i + 42], out [i + 43],
out [i + 44], out [i + 45], out [i + 46], out [i + 47],
out [i + 48], out [i + 49], out [i + 50], out [i + 51],
out [i + 52], out [i + 53], out [i + 54], out [i + 55],
out [i + 56], out [i + 57], out [i + 58], out [i + 59],
out [i + 60], out [i + 61], out [i + 62], out [i + 63] = string_byte (str, i, i + 63)
end
out = crypto.TruncateArray (out, #str)
return out
end
-- Converts an array of uint8s to a string destructively
function crypto.UInt8ArrayToString (array, startIndex)
startIndex = startIndex or 1
-- Process pairs of uint8s
local length = #array - startIndex + 1
local endIndex = #array
if length % 2 == 1 then endIndex = endIndex - 1 end
local j = startIndex
for i = startIndex, endIndex, 2 do
array [j] = byteCharacters2 [array [i] + array [i + 1] * 256]
j = j + 1
end
-- Process remaining uint8 if there is one
if length % 2 == 1 then
array [j] = byteCharacters [array [#array]]
j = j + 1
end
return table_concat (array, nil, startIndex, j - 1)
end
local oneOver64 = 1 / 64
-- Converts a string to an array of uint32s
function crypto.StringToUInt32Array (str, out)
out = out or {}
out.n = #str
local fullChunkCount = math_floor (#str * oneOver64)
local fullChunkCountMinusOne = fullChunkCount - 1
for i = 0, fullChunkCountMinusOne do
local uint80, uint81, uint82, uint83,
uint84, uint85, uint86, uint87,
uint88, uint89, uint810, uint811,
uint812, uint813, uint814, uint815,
uint816, uint817, uint818, uint819,
uint820, uint821, uint822, uint823,
uint824, uint825, uint826, uint827,
uint828, uint829, uint830, uint831,
uint832, uint833, uint834, uint835,
uint836, uint837, uint838, uint839,
uint840, uint841, uint842, uint843,
uint844, uint845, uint846, uint847,
uint848, uint849, uint850, uint851,
uint852, uint853, uint854, uint855,
uint856, uint857, uint858, uint859,
uint860, uint861, uint862, uint863 = string_byte (str, i * 64 + 1, i * 64 + 64)
out [i * 16 + 1] = uint80 + uint81 * 256 + uint82 * 65536 + uint83 * 16777216
out [i * 16 + 2] = uint84 + uint85 * 256 + uint86 * 65536 + uint87 * 16777216
out [i * 16 + 3] = uint88 + uint89 * 256 + uint810 * 65536 + uint811 * 16777216
out [i * 16 + 4] = uint812 + uint813 * 256 + uint814 * 65536 + uint815 * 16777216
out [i * 16 + 5] = uint816 + uint817 * 256 + uint818 * 65536 + uint819 * 16777216
out [i * 16 + 6] = uint820 + uint821 * 256 + uint822 * 65536 + uint823 * 16777216
out [i * 16 + 7] = uint824 + uint825 * 256 + uint826 * 65536 + uint827 * 16777216
out [i * 16 + 8] = uint828 + uint829 * 256 + uint830 * 65536 + uint831 * 16777216
out [i * 16 + 9] = uint832 + uint833 * 256 + uint834 * 65536 + uint835 * 16777216
out [i * 16 + 10] = uint836 + uint837 * 256 + uint838 * 65536 + uint839 * 16777216
out [i * 16 + 11] = uint840 + uint841 * 256 + uint842 * 65536 + uint843 * 16777216
out [i * 16 + 12] = uint844 + uint845 * 256 + uint846 * 65536 + uint847 * 16777216
out [i * 16 + 13] = uint848 + uint849 * 256 + uint850 * 65536 + uint851 * 16777216
out [i * 16 + 14] = uint852 + uint853 * 256 + uint854 * 65536 + uint855 * 16777216
out [i * 16 + 15] = uint856 + uint857 * 256 + uint858 * 65536 + uint859 * 16777216
out [i * 16 + 16] = uint860 + uint861 * 256 + uint862 * 65536 + uint863 * 16777216
end
if #str % 64 ~= 0 then
local startIndex = #str - #str % 64 + 1
for i = startIndex, #str, 4 do
local uint80, uint81, uint82, uint83 = string_byte (str, i, i + 3)
uint80, uint81, uint82, uint83 = uint80 or 0, uint81 or 0, uint82 or 0, uint83 or 0
out [#out + 1] = uint80 + uint81 * 256 + uint82 * 65536 + uint83 * 16777216
end
end
out = crypto.TruncateArray (out, math_ceil (#str * 0.25))
return out
end
-- Converts an array of int32s to a string
local bit = bit
local oneOver65536 = 1 / 65536
function crypto.Int32ArrayToString (array, startIndex)
startIndex = startIndex or 1
local length = (array.n or (#array * 4)) - (startIndex - 1) * 4
local t = {}
for i = startIndex, #array do
local uint32 = array [i]
local uint80 = uint32 % 256 uint32 = uint32 - uint80
local uint81 = uint32 % 65536 uint32 = uint32 - uint81 uint32 = uint32 * oneOver65536
local uint82 = uint32 % 256 uint32 = uint32 - uint82
local uint83 = uint32 % 65536
t [#t + 1] = byteCharacters2 [uint80 + uint81]
t [#t + 1] = byteCharacters2 [uint82 + uint83]
end
if length % 4 == 1 then
t [#t] = nil
t [#t] = string_sub (t [#t], 1, 1)
elseif length % 4 == 2 then
t [#t] = nil
elseif length % 4 == 3 then
t [#t] = string_sub (t [#t], 1, 1)
end
return table_concat (t)
end
-- Converts an array of uint32s to a string
function crypto.UInt32ArrayToString (array, startIndex)
return crypto.Int32ArrayToString (array, startIndex)
end
return crypto