Moonshark/modules/crypto/crypto.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