Skip to content

Instantly share code, notes, and snippets.

@LolloDev5123
Created April 13, 2025 15:30
Show Gist options
  • Select an option

  • Save LolloDev5123/2ac28c3484e97cab3d96037d3e5e0062 to your computer and use it in GitHub Desktop.

Select an option

Save LolloDev5123/2ac28c3484e97cab3d96037d3e5e0062 to your computer and use it in GitHub Desktop.
Swiss, an Indirecta Crypto Utility Module
-- !native
--[[
`/shdmmmmmmmmmd-`ymmmddyo:` // sm- /h/ --
`yNMMMMMMMMMMMMm-.dMMMMMMMMMN+ `MN `-:::.` .-:-hM- -o- .-::. .::-. `.:::` MN--. `-::-.
yMMMMMMMMMMMMMd.:NMMMMMMMMMMMM+ `MN yMs+oNh oNy++mM- +Mo -Mm++:`hmo+yN+ .dmo++- MNoo/ `o+odN:
yMMMMMMMMMMMMy`+NMMMMMMMMMMMMM+ `MN yM: dM. MN yM- +Mo -Mh /Mmss sM+ MN +h ohMo
`yNMMMMMMMMMo`sMMMMMMMMMMMMMNo `MN yM: dM. oNy//dM- +Mo -Mh `dNs++o. -mm+//- dM+/+ mN+/sMo
`/shddddd/ odddddddddddho:` :: .:` -: `:///-` .:. `:- .://:` `-///. `-//: `-///:.
Licensed under GNU General Public License v3.0
]]
-- Swiss, an Indirecta Crypto Utility Module
-- LZW Compression + Ascii85 Encoding & Pseudo-Random Number Generation
-- LZW + ASCII85 + PRNG Module in Roblox Luau
local Swiss = {} :: {
-- LZW functions
compress: (input: string) -> string,
decompress: (ascii85Data: string) -> string,
-- ASCII85 functions
ascii85: {
encode: (data: string) -> string,
decode: (ascii85: string) -> string,
},
-- PRNG functions (53-bit seed based, generating 32-bit numbers)
prng: {
set_seed: (seed: number) -> (),
get_seed: () -> number,
get_random_32: () -> number,
},
}
------------------------------------------------------------
-- LZW Compression/Decompression (using 16-bit code packing)
------------------------------------------------------------
function Swiss.compress(input: string): string
-- Initialize dictionary with all single-byte characters.
local dict: { [string]: number } = {}
for i = 0, 255 do
dict[string.char(i)] = i
end
local dictSize: number = 256
local codes = {} :: { number }
local w = ""
-- Build the dictionary.
for i = 1, #input do
local c = input:sub(i, i)
local wc = w .. c
if dict[wc] then
w = wc
else
table.insert(codes, dict[w])
dict[wc] = dictSize
dictSize += 1
w = c
end
end
if w ~= "" then
table.insert(codes, dict[w])
end
-- Pack 16-bit codes into a binary string.
local bytes = {} :: { string }
for _, code in ipairs(codes) do
-- Write high byte then low byte.
bytes[#bytes + 1] = string.char(math.floor(code / 256))
bytes[#bytes + 1] = string.char(code % 256)
end
local binaryData = table.concat(bytes)
-- Encode the binary data to Adobe ASCII85 format.
return Swiss.ascii85.encode(binaryData)
end
function Swiss.decompress(ascii85Data: string): string
-- Decode ASCII85 to binary.
local binaryData = Swiss.ascii85.decode(ascii85Data)
local codes = {} :: { number }
-- Unpack 16-bit codes.
for i = 1, #binaryData, 2 do
local high = binaryData:byte(i)
local low = binaryData:byte(i + 1)
table.insert(codes, high * 256 + low)
end
-- Initialize dictionary for decompression.
local dict = {} :: { [number]: string }
for i = 0, 255 do
dict[i] = string.char(i)
end
local dictSize: number = 256
-- Decompress the codes.
local w = dict[codes[1]]
local resultParts = { w }
for i = 2, #codes do
local k = codes[i]
local entry: string
if dict[k] then
entry = dict[k]
elseif k == dictSize then
entry = w .. w:sub(1, 1) -- special case
else
error("LZW decompress error: Invalid code " .. k)
end
resultParts[#resultParts + 1] = entry
dict[dictSize] = w .. entry:sub(1, 1)
dictSize += 1
w = entry
end
return table.concat(resultParts)
end
------------------------------------------------------------
-- ASCII85 Encode/Decode (Adobe style with <~ and ~> delimiters)
------------------------------------------------------------
Swiss.ascii85 = {} :: {
encode: (data: string) -> string,
decode: (ascii85: string) -> string,
}
function Swiss.ascii85.encode(data: string): string
local originalLength = #data
local pad = (4 - (originalLength % 4)) % 4
local padded = data .. string.rep("\0", pad)
local resultParts = { "<~" }
local groupCount = #padded // 4
for i = 1, groupCount do
local chunk = padded:sub((i - 1) * 4 + 1, i * 4)
-- Convert 4-byte chunk to a 32-bit unsigned integer.
local value = 0
for j = 1, 4 do
value = value * 256 + chunk:byte(j)
end
-- For full groups of zero, use shorthand ("z") except in a padded final group.
if value == 0 and not (i == groupCount and pad > 0) then
resultParts[#resultParts + 1] = "z"
else
local block = {} :: { [number]: string }
-- Produce 5 ASCII85 characters.
for j = 1, 5 do
block[j] = string.char((value % 85) + 33)
value = math.floor(value / 85)
end
-- Append characters in reverse order.
for j = 5, 1, -1 do
resultParts[#resultParts + 1] = block[j]
end
end
end
-- Remove extra encoded characters corresponding to padding.
if pad > 0 then
local res = table.concat(resultParts)
res = res:sub(1, #res - (4 - pad))
resultParts = { res }
end
resultParts[#resultParts + 1] = "~>"
return table.concat(resultParts)
end
function Swiss.ascii85.decode(ascii85: string): string
-- Remove Adobe delimiters.
ascii85 = ascii85:gsub("^%s*<~", ""):gsub("~>%s*$", "")
-- Expand shorthand "z" to "!!!!!".
ascii85 = ascii85:gsub("z", "!!!!!")
local outputBytes = {} :: { string }
local block = {} :: { [number]: number }
local count = 0
local i = 1
while i <= #ascii85 do
local c = ascii85:sub(i, i)
if not c:match("%s") then
count += 1
block[count] = c:byte() - 33
if count == 5 then
local value = (((block[1] * 85 + block[2]) * 85 + block[3]) * 85 + block[4]) * 85 + block[5]
table.insert(outputBytes, string.char(math.floor(value / 2^24) % 256))
table.insert(outputBytes, string.char(math.floor(value / 2^16) % 256))
table.insert(outputBytes, string.char(math.floor(value / 2^8) % 256))
table.insert(outputBytes, string.char(value % 256))
count = 0
end
end
i += 1
end
if count > 0 then
-- Pad the block if necessary.
for j = count + 1, 5 do
block[j] = 84 -- pad with value corresponding to 'u'
end
local value = (((block[1] * 85 + block[2]) * 85 + block[3]) * 85 + block[4]) * 85 + block[5]
-- Output only count - 1 bytes.
for j = 1, count - 1 do
table.insert(outputBytes, string.char(math.floor(value / (2^(8 * (4 - j))) ) % 256))
end
end
return table.concat(outputBytes)
end
------------------------------------------------------------
-- PRNG Implementation (53-bit seed based, generating 32-bit integers)
------------------------------------------------------------
Swiss.prng = {} :: {
set_seed: (seed: number) -> (),
get_seed: () -> number,
get_random_32: () -> number,
}
-- Internal PRNG state (53 bits in total)
local prng_state_45 = 0 -- Range: 0 .. (2^45 - 1)
local prng_state_8 = 2 -- Range: 2 .. 256
-- Secret keys (derived from 57 secret bits)
local secret_key_6 = 58 -- 6-bit arbitrary (0..63)
local secret_key_7 = 110 -- 7-bit arbitrary (0..127)
local secret_key_44 = 3580861008710 -- 44-bit arbitrary (0..17592186044415)
local floor = math.floor
-- Compute a primitive root modulo 257 (one of 128 possible roots)
local function primitive_root_257(idx: number): number
local g, m, d = 1, 128, 2 * idx + 1
repeat
-- Multiply by itself and adjust with multiplier (3 when condition met)
g = (g * g * ((d >= m) and 3 or 1)) % 257
m = m / 2
d = d % m
until m < 1
return g
end
local param_mul_8 = primitive_root_257(secret_key_7)
local param_mul_45 = secret_key_6 * 4 + 1
local param_add_45 = secret_key_44 * 2 + 1
local PRNG_MOD_45 = 35184372088832 -- 2^45
function Swiss.prng.set_seed(seed_53: number)
-- Set the internal state from a 53-bit seed.
prng_state_45 = seed_53 % PRNG_MOD_45
prng_state_8 = floor(seed_53 / PRNG_MOD_45) % 255 + 2
end
function Swiss.prng.get_seed(): number
-- Return the current 53-bit seed representing the internal state.
return (prng_state_8 - 2) * PRNG_MOD_45 + prng_state_45
end
function Swiss.prng.get_random_32(): number
-- Update state_45 using an LCG with full period 2^45.
prng_state_45 = (prng_state_45 * param_mul_45 + param_add_45) % PRNG_MOD_45
-- Update state_8 using a Lehmer RNG; skip state = 1 to ensure coprime with 2^45.
repeat
prng_state_8 = (prng_state_8 * param_mul_8) % 257
until prng_state_8 ~= 1
-- Mix the two state parts: shift and rotate "state_45" by a variable amount.
local r = prng_state_8 % 32
local n = floor(prng_state_45 / 2^(13 - (prng_state_8 - r) / 32)) % 2^32 / 2^r
return floor((n % 1) * 2^32) + floor(n)
end
------------------------------------------------------------
-- Module Return
------------------------------------------------------------
return Swiss
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment