Moonshark/tests/crypto.lua

333 lines
10 KiB
Lua

require("tests")
local crypto = require("crypto")
-- Test data
local test_data = "Hello, World!"
local test_key = "secret-key-123"
-- ======================================================================
-- ENCODING/DECODING TESTS
-- ======================================================================
test("Base64 Encoding/Decoding", function()
local encoded = crypto.base64_encode(test_data)
assert_equal(type(encoded), "string")
assert(#encoded > 0, "encoded string should not be empty")
local decoded = crypto.base64_decode(encoded)
assert_equal(decoded, test_data)
end)
test("Base64 URL Encoding/Decoding", function()
local encoded = crypto.base64_url_encode(test_data)
assert_equal(type(encoded), "string")
local decoded = crypto.base64_url_decode(encoded)
assert_equal(decoded, test_data)
end)
test("Hex Encoding/Decoding", function()
local encoded = crypto.hex_encode(test_data)
assert_equal(type(encoded), "string")
assert(encoded:match("^[0-9a-f]+$"), "hex should only contain hex characters")
local decoded = crypto.hex_decode(encoded)
assert_equal(decoded, test_data)
end)
test("Encoding Chain", function()
local chain_encoded = crypto.encode_chain(test_data, {"hex", "base64"})
local chain_decoded = crypto.decode_chain(chain_encoded, {"hex", "base64"})
assert_equal(chain_decoded, test_data)
end)
-- ======================================================================
-- HASHING TESTS
-- ======================================================================
test("MD5 Hash", function()
local hash = crypto.md5(test_data)
assert_equal(type(hash), "string")
assert_equal(#hash, 32) -- MD5 is 32 hex characters
assert(hash:match("^[0-9a-f]+$"), "hash should be hex")
-- Same input should produce same hash
assert_equal(crypto.md5(test_data), hash)
end)
test("SHA1 Hash", function()
local hash = crypto.sha1(test_data)
assert_equal(type(hash), "string")
assert_equal(#hash, 40) -- SHA1 is 40 hex characters
assert(hash:match("^[0-9a-f]+$"), "hash should be hex")
end)
test("SHA256 Hash", function()
local hash = crypto.sha256(test_data)
assert_equal(type(hash), "string")
assert_equal(#hash, 64) -- SHA256 is 64 hex characters
assert(hash:match("^[0-9a-f]+$"), "hash should be hex")
end)
test("SHA512 Hash", function()
local hash = crypto.sha512(test_data)
assert_equal(type(hash), "string")
assert_equal(#hash, 128) -- SHA512 is 128 hex characters
assert(hash:match("^[0-9a-f]+$"), "hash should be hex")
end)
test("Hash Multiple Inputs", function()
local hash1 = crypto.hash_multiple({"hello", "world"})
local hash2 = crypto.hash_multiple({"hello", "world"})
local hash3 = crypto.hash_multiple({"world", "hello"})
assert_equal(hash1, hash2)
assert(hash1 ~= hash3, "different order should produce different hash")
end)
-- ======================================================================
-- HMAC TESTS
-- ======================================================================
test("HMAC SHA1", function()
local hmac = crypto.hmac_sha1(test_data, test_key)
assert_equal(type(hmac), "string")
assert_equal(#hmac, 40) -- SHA1 HMAC is 40 hex characters
assert(hmac:match("^[0-9a-f]+$"), "hmac should be hex")
end)
test("HMAC SHA256", function()
local hmac = crypto.hmac_sha256(test_data, test_key)
assert_equal(type(hmac), "string")
assert_equal(#hmac, 64) -- SHA256 HMAC is 64 hex characters
assert(hmac:match("^[0-9a-f]+$"), "hmac should be hex")
end)
test("MAC Functions", function()
local mac = crypto.mac(test_data, test_key)
assert_equal(type(mac), "string")
assert(#mac > 0, "mac should not be empty")
local valid = crypto.verify_mac(test_data, test_key, mac)
assert_equal(valid, true)
local invalid = crypto.verify_mac("different data", test_key, mac)
assert_equal(invalid, false)
end)
-- ======================================================================
-- UUID TESTS
-- ======================================================================
test("UUID Generation", function()
local uuid1 = crypto.uuid()
local uuid2 = crypto.uuid_v4()
assert_equal(type(uuid1), "string")
assert_equal(type(uuid2), "string")
assert_equal(#uuid1, 36) -- Standard UUID length
assert_equal(#uuid2, 36)
assert(uuid1 ~= uuid2, "UUIDs should be unique")
assert_equal(crypto.is_uuid(uuid1), true)
assert_equal(crypto.is_uuid(uuid2), true)
assert_equal(crypto.is_uuid("not-a-uuid"), false)
end)
-- ======================================================================
-- RANDOM GENERATION TESTS
-- ======================================================================
test("Random Bytes", function()
local bytes1 = crypto.random_bytes(16)
local bytes2 = crypto.random_bytes(16)
assert_equal(type(bytes1), "string")
assert_equal(#bytes1, 16)
assert(bytes1 ~= bytes2, "random bytes should be different")
end)
test("Random Hex", function()
local hex1 = crypto.random_hex(8)
local hex2 = crypto.random_hex(8)
assert_equal(type(hex1), "string")
assert_equal(#hex1, 16) -- 8 bytes = 16 hex characters
assert(hex1:match("^[0-9a-f]+$"), "should be hex")
assert(hex1 ~= hex2, "random hex should be different")
end)
test("Random String", function()
local str1 = crypto.random_string(10)
local str2 = crypto.random_string(10)
assert_equal(type(str1), "string")
assert_equal(#str1, 10)
assert(str1 ~= str2, "random strings should be different")
local custom = crypto.random_string(5, "abc")
assert_equal(#custom, 5)
assert(custom:match("^[abc]+$"), "should only contain specified characters")
end)
test("Random Alphanumeric", function()
local str = crypto.random_alphanumeric(20)
assert_equal(#str, 20)
assert(str:match("^[a-zA-Z0-9]+$"), "should be alphanumeric")
end)
test("Random Password", function()
local pass1 = crypto.random_password(12)
local pass2 = crypto.random_password(12, true) -- with symbols
assert_equal(#pass1, 12)
assert_equal(#pass2, 12)
assert(pass1 ~= pass2, "passwords should be different")
end)
test("Token Generation", function()
local token1 = crypto.token(32)
local token2 = crypto.token(32)
assert_equal(#token1, 64) -- 32 bytes = 64 hex characters
assert(token1:match("^[0-9a-f]+$"), "token should be hex")
assert(token1 ~= token2, "tokens should be unique")
end)
test("Nonce Generation", function()
local nonce1 = crypto.nonce()
local nonce2 = crypto.nonce(32)
assert_equal(#nonce1, 32) -- default 16 bytes = 32 hex
assert_equal(#nonce2, 64) -- 32 bytes = 64 hex
assert(nonce1 ~= nonce2, "nonces should be unique")
end)
-- ======================================================================
-- UTILITY TESTS
-- ======================================================================
test("Secure Compare", function()
local str1 = "hello"
local str2 = "hello"
local str3 = "world"
assert_equal(crypto.secure_compare(str1, str2), true)
assert_equal(crypto.secure_compare(str1, str3), false)
end)
test("Checksum Functions", function()
local checksum = crypto.checksum(test_data)
assert_equal(type(checksum), "string")
local valid = crypto.verify_checksum(test_data, checksum)
assert_equal(valid, true)
local invalid = crypto.verify_checksum("different", checksum)
assert_equal(invalid, false)
end)
test("XOR Encryption", function()
local key = "mykey"
local encrypted = crypto.xor_encrypt(test_data, key)
local decrypted = crypto.xor_decrypt(encrypted, key)
assert_equal(decrypted, test_data)
assert(encrypted ~= test_data, "encrypted should be different")
end)
test("Hash Chain", function()
local chain1 = crypto.hash_chain(test_data, 100)
local chain2 = crypto.hash_chain(test_data, 100)
local chain3 = crypto.hash_chain(test_data, 101)
assert_equal(chain1, chain2)
assert(chain1 ~= chain3, "different iterations should produce different results")
end)
test("Key Derivation", function()
local derived1, salt1 = crypto.derive_key("password", "salt", 1000)
local derived2, salt2 = crypto.derive_key("password", salt1, 1000)
assert_equal(derived1, derived2)
assert_equal(salt1, salt2)
assert_equal(type(derived1), "string")
assert(#derived1 > 0, "derived key should not be empty")
end)
test("Fingerprint", function()
local data = {name = "test", value = 42}
local fp1 = crypto.fingerprint(data)
local fp2 = crypto.fingerprint(data)
assert_equal(fp1, fp2)
assert_equal(type(fp1), "string")
assert(#fp1 > 0, "fingerprint should not be empty")
end)
test("Integrity Check", function()
local check = crypto.integrity_check(test_data)
assert_equal(check.data, test_data)
assert_equal(type(check.hash), "string")
assert_equal(type(check.timestamp), "number")
assert_equal(type(check.uuid), "string")
local valid = crypto.verify_integrity(check)
assert_equal(valid, true)
-- Tamper with data
check.data = "tampered"
local invalid = crypto.verify_integrity(check)
assert_equal(invalid, false)
end)
-- ======================================================================
-- ERROR HANDLING TESTS
-- ======================================================================
test("Error Handling", function()
-- Invalid base64
local success, err = pcall(crypto.base64_decode, "invalid===base64")
assert_equal(success, false)
-- Invalid hex
local success2, err2 = pcall(crypto.hex_decode, "invalid_hex")
assert_equal(success2, false)
-- Invalid UUID validation (returns boolean, doesn't throw)
assert_equal(crypto.is_uuid("not-a-uuid"), false)
assert_equal(crypto.is_uuid(""), false)
assert_equal(crypto.is_uuid("12345"), false)
end)
-- ======================================================================
-- PERFORMANCE TESTS
-- ======================================================================
test("Performance Test", function()
local large_data = string.rep("test data for performance ", 1000)
local start = os.clock()
local hash = crypto.sha256(large_data)
local hash_time = os.clock() - start
start = os.clock()
local encoded = crypto.base64_encode(large_data)
local encode_time = os.clock() - start
start = os.clock()
local decoded = crypto.base64_decode(encoded)
local decode_time = os.clock() - start
print(string.format(" SHA256 of %d bytes: %.3fs", #large_data, hash_time))
print(string.format(" Base64 encode: %.3fs", encode_time))
print(string.format(" Base64 decode: %.3fs", decode_time))
assert_equal(decoded, large_data)
assert_equal(type(hash), "string")
end)
summary()
test_exit()