mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 21:53:46 +03:00
505 lines
15 KiB
Lua
505 lines
15 KiB
Lua
--[[
|
|
| 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 |