531 lines
13 KiB
Lua
531 lines
13 KiB
Lua
local crypto = {}
|
|
|
|
-- ======================================================================
|
|
-- ENCODING / DECODING
|
|
-- ======================================================================
|
|
|
|
function crypto.base64_encode(data)
|
|
local result, err = moonshark.base64_encode(data)
|
|
if not result then
|
|
error(err)
|
|
end
|
|
return result
|
|
end
|
|
|
|
function crypto.base64_decode(data)
|
|
local result, err = moonshark.base64_decode(data)
|
|
if not result then
|
|
error(err)
|
|
end
|
|
return result
|
|
end
|
|
|
|
function crypto.base64_url_encode(data)
|
|
local result, err = moonshark.base64_url_encode(data)
|
|
if not result then
|
|
error(err)
|
|
end
|
|
return result
|
|
end
|
|
|
|
function crypto.base64_url_decode(data)
|
|
local result, err = moonshark.base64_url_decode(data)
|
|
if not result then
|
|
error(err)
|
|
end
|
|
return result
|
|
end
|
|
|
|
function crypto.hex_encode(data)
|
|
local result, err = moonshark.hex_encode(data)
|
|
if not result then
|
|
error(err)
|
|
end
|
|
return result
|
|
end
|
|
|
|
function crypto.hex_decode(data)
|
|
local result, err = moonshark.hex_decode(data)
|
|
if not result then
|
|
error(err)
|
|
end
|
|
return result
|
|
end
|
|
|
|
-- ======================================================================
|
|
-- HASHING FUNCTIONS
|
|
-- ======================================================================
|
|
|
|
function crypto.md5(data)
|
|
local result, err = moonshark.md5_hash(data)
|
|
if not result then
|
|
error(err)
|
|
end
|
|
return result
|
|
end
|
|
|
|
function crypto.sha1(data)
|
|
local result, err = moonshark.sha1_hash(data)
|
|
if not result then
|
|
error(err)
|
|
end
|
|
return result
|
|
end
|
|
|
|
function crypto.sha256(data)
|
|
local result, err = moonshark.sha256_hash(data)
|
|
if not result then
|
|
error(err)
|
|
end
|
|
return result
|
|
end
|
|
|
|
function crypto.sha512(data)
|
|
local result, err = moonshark.sha512_hash(data)
|
|
if not result then
|
|
error(err)
|
|
end
|
|
return result
|
|
end
|
|
|
|
-- Hash file contents
|
|
function crypto.hash_file(path, algorithm)
|
|
algorithm = algorithm or "sha256"
|
|
|
|
if not moonshark.file_exists(path) then
|
|
error("File not found: " .. path)
|
|
end
|
|
|
|
local content = moonshark.file_read(path)
|
|
if not content then
|
|
error("Failed to read file: " .. path)
|
|
end
|
|
|
|
if algorithm == "md5" then
|
|
return crypto.md5(content)
|
|
elseif algorithm == "sha1" then
|
|
return crypto.sha1(content)
|
|
elseif algorithm == "sha256" then
|
|
return crypto.sha256(content)
|
|
elseif algorithm == "sha512" then
|
|
return crypto.sha512(content)
|
|
else
|
|
error("Unsupported hash algorithm: " .. algorithm)
|
|
end
|
|
end
|
|
|
|
-- ======================================================================
|
|
-- HMAC FUNCTIONS
|
|
-- ======================================================================
|
|
|
|
function crypto.hmac_sha1(message, key)
|
|
local result, err = moonshark.hmac_sha1(message, key)
|
|
if not result then
|
|
error(err)
|
|
end
|
|
return result
|
|
end
|
|
|
|
function crypto.hmac_sha256(message, key)
|
|
local result, err = moonshark.hmac_sha256(message, key)
|
|
if not result then
|
|
error(err)
|
|
end
|
|
return result
|
|
end
|
|
|
|
-- ======================================================================
|
|
-- UUID FUNCTIONS
|
|
-- ======================================================================
|
|
|
|
function crypto.uuid()
|
|
return moonshark.uuid_generate()
|
|
end
|
|
|
|
function crypto.uuid_v4()
|
|
return moonshark.uuid_generate_v4()
|
|
end
|
|
|
|
function crypto.is_uuid(str)
|
|
return moonshark.uuid_validate(str)
|
|
end
|
|
|
|
-- ======================================================================
|
|
-- RANDOM GENERATORS
|
|
-- ======================================================================
|
|
|
|
function crypto.random_bytes(length)
|
|
local result, err = moonshark.random_bytes(length)
|
|
if not result then
|
|
error(err)
|
|
end
|
|
return result
|
|
end
|
|
|
|
function crypto.random_hex(length)
|
|
local result, err = moonshark.random_hex(length)
|
|
if not result then
|
|
error(err)
|
|
end
|
|
return result
|
|
end
|
|
|
|
function crypto.random_string(length, charset)
|
|
local result, err = moonshark.random_string(length, charset)
|
|
if not result then
|
|
error(err)
|
|
end
|
|
return result
|
|
end
|
|
|
|
-- Generate random alphanumeric string
|
|
function crypto.random_alphanumeric(length)
|
|
return crypto.random_string(length, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
|
|
end
|
|
|
|
-- Generate random password with mixed characters
|
|
function crypto.random_password(length, include_symbols)
|
|
length = length or 12
|
|
local charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
|
|
|
if include_symbols then
|
|
charset = charset .. "!@#$%^&*()_+-=[]{}|;:,.<>?"
|
|
end
|
|
|
|
return crypto.random_string(length, charset)
|
|
end
|
|
|
|
-- Generate cryptographically secure token
|
|
function crypto.token(length)
|
|
length = length or 32
|
|
return crypto.random_hex(length)
|
|
end
|
|
|
|
-- ======================================================================
|
|
-- UTILITY FUNCTIONS
|
|
-- ======================================================================
|
|
|
|
function crypto.secure_compare(a, b)
|
|
return moonshark.secure_compare(a, b)
|
|
end
|
|
|
|
-- Generate checksum for data integrity
|
|
function crypto.checksum(data, algorithm)
|
|
algorithm = algorithm or "sha256"
|
|
return crypto.hash_file and crypto[algorithm] and crypto[algorithm](data) or error("Invalid algorithm")
|
|
end
|
|
|
|
-- Verify data against checksum
|
|
function crypto.verify_checksum(data, expected, algorithm)
|
|
algorithm = algorithm or "sha256"
|
|
local actual = crypto[algorithm](data)
|
|
return crypto.secure_compare(actual, expected)
|
|
end
|
|
|
|
-- Simple encryption using XOR (not cryptographically secure)
|
|
function crypto.xor_encrypt(data, key)
|
|
local result = {}
|
|
local key_len = #key
|
|
|
|
for i = 1, #data do
|
|
local data_byte = string.byte(data, i)
|
|
local key_byte = string.byte(key, ((i - 1) % key_len) + 1)
|
|
table.insert(result, string.char(bit32 and bit32.bxor(data_byte, key_byte) or bit.bxor(data_byte, key_byte)))
|
|
end
|
|
|
|
return table.concat(result)
|
|
end
|
|
|
|
-- XOR decryption (same as encryption)
|
|
function crypto.xor_decrypt(data, key)
|
|
return crypto.xor_encrypt(data, key)
|
|
end
|
|
|
|
-- Generate hash chain for proof of work
|
|
function crypto.hash_chain(data, iterations, algorithm)
|
|
iterations = iterations or 1000
|
|
algorithm = algorithm or "sha256"
|
|
|
|
local result = data
|
|
for i = 1, iterations do
|
|
result = crypto[algorithm](result)
|
|
end
|
|
return result
|
|
end
|
|
|
|
-- Key derivation using PBKDF2-like approach (simplified)
|
|
function crypto.derive_key(password, salt, iterations, algorithm)
|
|
iterations = iterations or 10000
|
|
algorithm = algorithm or "sha256"
|
|
salt = salt or crypto.random_hex(16)
|
|
|
|
local derived = password .. salt
|
|
for i = 1, iterations do
|
|
derived = crypto[algorithm](derived)
|
|
end
|
|
|
|
return derived, salt
|
|
end
|
|
|
|
-- Generate nonce (number used once)
|
|
function crypto.nonce(length)
|
|
length = length or 16
|
|
return crypto.random_hex(length)
|
|
end
|
|
|
|
-- Create message authentication code
|
|
function crypto.mac(message, key, algorithm)
|
|
algorithm = algorithm or "sha256"
|
|
return crypto["hmac_" .. algorithm](message, key)
|
|
end
|
|
|
|
-- Verify message authentication code
|
|
function crypto.verify_mac(message, key, mac, algorithm)
|
|
algorithm = algorithm or "sha256"
|
|
local expected = crypto.mac(message, key, algorithm)
|
|
return crypto.secure_compare(expected, mac)
|
|
end
|
|
|
|
-- ======================================================================
|
|
-- CONVENIENCE FUNCTIONS
|
|
-- ======================================================================
|
|
|
|
-- One-shot encoding chain
|
|
function crypto.encode_chain(data, formats)
|
|
formats = formats or {"base64"}
|
|
local result = data
|
|
|
|
for _, format in ipairs(formats) do
|
|
if format == "base64" then
|
|
result = crypto.base64_encode(result)
|
|
elseif format == "base64url" then
|
|
result = crypto.base64_url_encode(result)
|
|
elseif format == "hex" then
|
|
result = crypto.hex_encode(result)
|
|
else
|
|
error("Unknown encoding format: " .. format)
|
|
end
|
|
end
|
|
|
|
return result
|
|
end
|
|
|
|
-- One-shot decoding chain (reverse order)
|
|
function crypto.decode_chain(data, formats)
|
|
formats = formats or {"base64"}
|
|
local result = data
|
|
|
|
-- Reverse the formats for decoding
|
|
for i = #formats, 1, -1 do
|
|
local format = formats[i]
|
|
if format == "base64" then
|
|
result = crypto.base64_decode(result)
|
|
elseif format == "base64url" then
|
|
result = crypto.base64_url_decode(result)
|
|
elseif format == "hex" then
|
|
result = crypto.hex_decode(result)
|
|
else
|
|
error("Unknown decoding format: " .. format)
|
|
end
|
|
end
|
|
|
|
return result
|
|
end
|
|
|
|
-- Hash multiple inputs
|
|
function crypto.hash_multiple(inputs, algorithm)
|
|
algorithm = algorithm or "sha256"
|
|
local combined = table.concat(inputs, "")
|
|
return crypto[algorithm](combined)
|
|
end
|
|
|
|
-- Create fingerprint from table data
|
|
function crypto.fingerprint(data, algorithm)
|
|
algorithm = algorithm or "sha256"
|
|
return crypto[algorithm](json.encode(data))
|
|
end
|
|
|
|
-- Simple data integrity check
|
|
function crypto.integrity_check(data)
|
|
return {
|
|
data = data,
|
|
hash = crypto.sha256(data),
|
|
timestamp = os.time(),
|
|
uuid = crypto.uuid()
|
|
}
|
|
end
|
|
|
|
-- Verify integrity check
|
|
function crypto.verify_integrity(check)
|
|
if not check.data or not check.hash then
|
|
return false
|
|
end
|
|
|
|
local expected = crypto.sha256(check.data)
|
|
return crypto.secure_compare(expected, check.hash)
|
|
end
|
|
|
|
-- ======================================================================
|
|
-- PASSWORD HASHING
|
|
-- ======================================================================
|
|
|
|
-- Generic password hashing (defaults to argon2id)
|
|
function crypto.hash_password(password, algorithm, options)
|
|
algorithm = algorithm or "argon2id"
|
|
options = options or {}
|
|
|
|
local result, err
|
|
|
|
if algorithm == "argon2id" then
|
|
local time = options.time or 1
|
|
local memory = options.memory or 65536 -- 64MB in KB
|
|
local threads = options.threads or 4
|
|
local keylen = options.keylen or 32
|
|
result, err = moonshark.argon2_hash(password, time, memory, threads, keylen)
|
|
|
|
elseif algorithm == "bcrypt" then
|
|
local cost = options.cost or 12
|
|
result, err = moonshark.bcrypt_hash(password, cost)
|
|
|
|
elseif algorithm == "scrypt" then
|
|
local N = options.N or 32768
|
|
local r = options.r or 8
|
|
local p = options.p or 1
|
|
local keylen = options.keylen or 32
|
|
result, err = moonshark.scrypt_hash(password, N, r, p, keylen)
|
|
|
|
elseif algorithm == "pbkdf2" then
|
|
local iterations = options.iterations or 100000
|
|
local keylen = options.keylen or 32
|
|
result, err = moonshark.pbkdf2_hash(password, iterations, keylen)
|
|
|
|
else
|
|
error("unsupported algorithm: " .. algorithm)
|
|
end
|
|
|
|
if not result then
|
|
error(err)
|
|
end
|
|
return result
|
|
end
|
|
|
|
-- Generic password verification (auto-detects algorithm)
|
|
function crypto.verify_password(password, hash)
|
|
return moonshark.password_verify(password, hash)
|
|
end
|
|
|
|
-- ======================================================================
|
|
-- ALGORITHM-SPECIFIC FUNCTIONS
|
|
-- ======================================================================
|
|
|
|
-- Argon2id hashing
|
|
function crypto.argon2_hash(password, options)
|
|
options = options or {}
|
|
local time = options.time or 1
|
|
local memory = options.memory or 65536
|
|
local threads = options.threads or 4
|
|
local keylen = options.keylen or 32
|
|
|
|
local result, err = moonshark.argon2_hash(password, time, memory, threads, keylen)
|
|
if not result then error(err) end
|
|
return result
|
|
end
|
|
|
|
function crypto.argon2_verify(password, hash)
|
|
return moonshark.argon2_verify(password, hash)
|
|
end
|
|
|
|
-- bcrypt hashing
|
|
function crypto.bcrypt_hash(password, cost)
|
|
cost = cost or 12
|
|
local result, err = moonshark.bcrypt_hash(password, cost)
|
|
if not result then error(err) end
|
|
return result
|
|
end
|
|
|
|
function crypto.bcrypt_verify(password, hash)
|
|
return moonshark.bcrypt_verify(password, hash)
|
|
end
|
|
|
|
-- scrypt hashing
|
|
function crypto.scrypt_hash(password, options)
|
|
options = options or {}
|
|
local N = options.N or 32768
|
|
local r = options.r or 8
|
|
local p = options.p or 1
|
|
local keylen = options.keylen or 32
|
|
|
|
local result, err = moonshark.scrypt_hash(password, N, r, p, keylen)
|
|
if not result then error(err) end
|
|
return result
|
|
end
|
|
|
|
function crypto.scrypt_verify(password, hash)
|
|
return moonshark.scrypt_verify(password, hash)
|
|
end
|
|
|
|
-- PBKDF2 hashing
|
|
function crypto.pbkdf2_hash(password, iterations, keylen)
|
|
iterations = iterations or 100000
|
|
keylen = keylen or 32
|
|
|
|
local result, err = moonshark.pbkdf2_hash(password, iterations, keylen)
|
|
if not result then error(err) end
|
|
return result
|
|
end
|
|
|
|
function crypto.pbkdf2_verify(password, hash)
|
|
return moonshark.pbkdf2_verify(password, hash)
|
|
end
|
|
|
|
-- ======================================================================
|
|
-- PASSWORD CONFIG PRESETS
|
|
-- ======================================================================
|
|
|
|
function crypto.hash_password_fast(password, algorithm)
|
|
algorithm = algorithm or "argon2id"
|
|
|
|
local options = {
|
|
argon2id = { time = 1, memory = 8192, threads = 1 },
|
|
bcrypt = { cost = 10 },
|
|
scrypt = { N = 16384, r = 8, p = 1 },
|
|
pbkdf2 = { iterations = 50000 }
|
|
}
|
|
|
|
return crypto.hash_password(password, algorithm, options[algorithm])
|
|
end
|
|
|
|
function crypto.hash_password_strong(password, algorithm)
|
|
algorithm = algorithm or "argon2id"
|
|
|
|
local options = {
|
|
argon2id = { time = 3, memory = 131072, threads = 4 },
|
|
bcrypt = { cost = 14 },
|
|
scrypt = { N = 65536, r = 8, p = 2 },
|
|
pbkdf2 = { iterations = 200000 }
|
|
}
|
|
|
|
return crypto.hash_password(password, algorithm, options[algorithm])
|
|
end
|
|
|
|
-- ======================================================================
|
|
-- UTILITY FUNCTIONS
|
|
-- ======================================================================
|
|
|
|
-- Detect algorithm from hash
|
|
function crypto.detect_algorithm(hash)
|
|
if hash:match("^%$argon2id%$") then
|
|
return "argon2id"
|
|
elseif hash:match("^%$2[aby]%$") then
|
|
return "bcrypt"
|
|
elseif hash:match("^%$scrypt%$") then
|
|
return "scrypt"
|
|
elseif hash:match("^%$pbkdf2%-sha256%$") then
|
|
return "pbkdf2"
|
|
else
|
|
return "unknown"
|
|
end
|
|
end
|
|
|
|
return crypto
|