mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-12 14:09:12 +00:00
Improve tests
Add definitions Align function name
This commit is contained in:
parent
2d2a8a2d7d
commit
5c47674d27
3 changed files with 128 additions and 53 deletions
|
@ -1,7 +1,7 @@
|
|||
-- Helper function to print test results
|
||||
local function assert_equal(actual, expected, message)
|
||||
if actual ~= expected then
|
||||
error(message .. ": expected " .. tostring(expected) .. ", got " .. tostring(actual))
|
||||
error("FAIL: " .. message .. ": expected " .. tostring(expected) .. ", got " .. tostring(actual))
|
||||
else
|
||||
print("PASS: " .. message)
|
||||
end
|
||||
|
@ -19,146 +19,153 @@ end
|
|||
local function test_rsa_keypair_generation()
|
||||
print('\27[1;7mTest RSA key pair generation \27[0m')
|
||||
local priv_key, pub_key = crypto.generatekeypair("rsa", 2048)
|
||||
assert_equal(type(priv_key), "string", "RSA private key generation")
|
||||
assert_equal(type(pub_key), "string", "RSA public key generation")
|
||||
assert_equal(type(priv_key), "string", "Private key type")
|
||||
assert_equal(type(pub_key), "string", "Public key type")
|
||||
end
|
||||
|
||||
-- Test ECDSA key pair generation
|
||||
local function test_ecdsa_keypair_generation()
|
||||
print('\n\27[1;7mTest ECDSA key pair generation \27[0m')
|
||||
local priv_key, pub_key = crypto.generatekeypair("ecdsa", "secp256r1")
|
||||
assert_equal(type(priv_key), "string", "ECDSA private key generation")
|
||||
assert_equal(type(pub_key), "string", "ECDSA public key generation")
|
||||
assert_equal(type(priv_key), "string", "Private key type")
|
||||
assert_equal(type(pub_key), "string", "Public key type")
|
||||
end
|
||||
|
||||
-- Test RSA encryption and decryption
|
||||
local function test_rsa_encryption_decryption()
|
||||
print('\n\27[1;7mTest RSA encryption and decryption \27[0m')
|
||||
local priv_key, pub_key = crypto.generatekeypair("rsa", 2048)
|
||||
assert(type(priv_key) == "string", "Private key type")
|
||||
assert(type(pub_key) == "string", "Public key type")
|
||||
local plaintext = "Hello, RSA!"
|
||||
local encrypted = crypto.encrypt("rsa", pub_key, plaintext)
|
||||
assert_equal(type(encrypted), "string", "RSA encryption")
|
||||
assert_equal(type(encrypted), "string", "Ciphertext type")
|
||||
local decrypted = crypto.decrypt("rsa", priv_key, encrypted)
|
||||
assert_equal(decrypted, plaintext, "RSA decryption")
|
||||
assert_equal(decrypted, plaintext, "Decrypted ciphertext matches plaintext")
|
||||
end
|
||||
|
||||
-- Test RSA signing and verification
|
||||
local function test_rsa_signing_verification()
|
||||
print('\n\27[1;7mTest RSA signing and verification \27[0m')
|
||||
local priv_key, pub_key = crypto.generatekeypair("rsa", 2048)
|
||||
assert(type(priv_key) == "string", "Private key type")
|
||||
assert(type(pub_key) == "string", "Public key type")
|
||||
local message = "Sign this message"
|
||||
local signature = crypto.sign("rsa", priv_key, message, "sha256")
|
||||
assert_equal(type(signature), "string", "RSA signing")
|
||||
assert_equal(type(signature), "string", "Signature type")
|
||||
local is_valid = crypto.verify("rsa", pub_key, message, signature, "sha256")
|
||||
assert_equal(is_valid, true, "RSA signature verification")
|
||||
assert_equal(is_valid, true, "Signature verification")
|
||||
end
|
||||
|
||||
-- Test ECDSA signing and verification
|
||||
local function test_ecdsa_signing_verification()
|
||||
print('\n\27[1;7mTest ECDSA signing and verification \27[0m')
|
||||
local priv_key, pub_key = crypto.generatekeypair("ecdsa", "secp256r1")
|
||||
assert(type(priv_key) == "string", "Private key type")
|
||||
assert(type(pub_key) == "string", "Public key type")
|
||||
local message = "Sign this message with ECDSA"
|
||||
local signature = crypto.sign("ecdsa", priv_key, message, "sha256")
|
||||
assert_equal(type(signature), "string", "ECDSA signing")
|
||||
assert_equal(type(signature), "string", "Signature type")
|
||||
local is_valid = crypto.verify("ecdsa", pub_key, message, signature, "sha256")
|
||||
assert_equal(is_valid, true, "ECDSA signature verification")
|
||||
assert_equal(is_valid, true, "Signature verification")
|
||||
end
|
||||
|
||||
-- Test AES key generation
|
||||
local function test_aes_key_generation()
|
||||
print('\n\27[1;7mTest AES key generation \27[0m')
|
||||
local key = crypto.generatekeypair('aes', 256) -- 256-bit key
|
||||
assert_equal(type(key), "string", "AES key generation")
|
||||
assert_equal(#key, 32, "AES key length (256 bits)")
|
||||
assert_equal(type(key), "string", "Key type")
|
||||
assert_equal(#key, 32, "Key length (256 bits)")
|
||||
end
|
||||
|
||||
-- Test AES encryption and decryption (CBC mode)
|
||||
local function test_aes_encryption_decryption()
|
||||
print('\n\27[1;7mTest AES encryption and decryption (CBC mode) \27[0m')
|
||||
local key = crypto.generatekeypair('aes',256) -- 256-bit key
|
||||
local key = crypto.generatekeypair('aes', 256) -- 256-bit key
|
||||
local plaintext = "Hello, AES CBC!"
|
||||
|
||||
-- Encrypt without providing IV (should auto-generate IV)
|
||||
print('\27[1mAES encryption (auto IV)\27[0m')
|
||||
local encrypted, iv = crypto.encrypt("aes", key, plaintext, nil)
|
||||
assert_equal(type(encrypted), "string", "AES encryption (CBC, auto IV)")
|
||||
assert_equal(type(iv), "string", "AES IV (auto-generated)")
|
||||
assert_equal(type(encrypted), "string", "Ciphertext type")
|
||||
assert_equal(type(iv), "string", "IV type")
|
||||
|
||||
-- Decrypt
|
||||
print('\n\27[1mAES decryption (auto IV)\27[0m')
|
||||
local decrypted = crypto.decrypt("aes", key, encrypted, iv)
|
||||
assert_equal(decrypted, plaintext, "AES decryption (CBC, auto IV)")
|
||||
assert_equal(decrypted, plaintext, "Decrypted ciphertext matches plaintext")
|
||||
|
||||
-- Encrypt with explicit IV
|
||||
print('\n\27[1mAES encryption (explicit IV)\27[0m')
|
||||
local iv2 = GetRandomBytes(16)
|
||||
local encrypted2, iv_used = crypto.encrypt("aes", key, plaintext, iv2)
|
||||
assert_equal(type(encrypted2), "string", "AES encryption (CBC, explicit IV)")
|
||||
assert_equal(iv_used, iv2, "AES IV (explicit)")
|
||||
assert_equal(type(encrypted2), "string", "Ciphertext type")
|
||||
assert_equal(iv_used, iv2, "IV match")
|
||||
|
||||
print('\n\27[1mAES decryption (explicit IV)\27[0m')
|
||||
local decrypted2 = crypto.decrypt("aes", key, encrypted2, iv2)
|
||||
assert_equal(decrypted2, plaintext, "AES decryption (CBC, explicit IV)")
|
||||
assert_equal(decrypted2, plaintext, "Decrypted ciphertext matches plaintext")
|
||||
end
|
||||
|
||||
-- Test AES encryption and decryption (CTR mode)
|
||||
local function test_aes_encryption_decryption_ctr()
|
||||
print('\n\27[1;7mTest AES encryption and decryption (CTR mode) \27[0m')
|
||||
local key = crypto.generatekeypair('aes',256)
|
||||
local key = crypto.generatekeypair('aes', 256)
|
||||
local plaintext = "Hello, AES CTR!"
|
||||
|
||||
-- Encrypt without providing IV (should auto-generate IV)
|
||||
print('\27[1mAES encryption (auto IV)\27[0m')
|
||||
local encrypted, iv = crypto.encrypt("aes", key, plaintext, nil, "ctr")
|
||||
assert_equal(type(encrypted), "string", "AES encryption (CTR, auto IV)")
|
||||
assert_equal(type(iv), "string", "AES IV (auto-generated, CTR)")
|
||||
assert_equal(type(encrypted), "string", "Ciphertext type")
|
||||
assert_equal(type(iv), "string", "IV type")
|
||||
|
||||
-- Decrypt
|
||||
print('\n\27[1mAES decryption (auto IV)\27[0m')
|
||||
local decrypted = crypto.decrypt("aes", key, encrypted, iv, "ctr")
|
||||
assert_equal(decrypted, plaintext, "AES decryption (CTR, auto IV)")
|
||||
assert_equal(decrypted, plaintext, "Decrypted ciphertext matches plaintext")
|
||||
|
||||
-- Encrypt with explicit IV
|
||||
print('\n\27[1mAES encryption (explicit IV)\27[0m')
|
||||
local iv2 = GetRandomBytes(16)
|
||||
local encrypted2, iv_used = crypto.encrypt("aes", key, plaintext, iv2, "ctr")
|
||||
assert_equal(type(encrypted2), "string", "AES encryption (CTR, explicit IV)")
|
||||
assert_equal(iv_used, iv2, "AES IV (explicit, CTR)")
|
||||
assert_equal(type(encrypted2), "string", "Ciphertext type")
|
||||
assert_equal(iv_used, iv2, "IV match")
|
||||
|
||||
print('\n\27[1mAES decryption (explicit IV)\27[0m')
|
||||
local decrypted2 = crypto.decrypt("aes", key, encrypted2, iv2, "ctr")
|
||||
assert_equal(decrypted2, plaintext, "AES decryption (CTR, explicit IV)")
|
||||
assert_equal(decrypted2, plaintext, "Decrypted ciphertext matches plaintext")
|
||||
end
|
||||
|
||||
-- Test AES encryption and decryption (GCM mode)
|
||||
local function test_aes_encryption_decryption_gcm()
|
||||
print('\n\27[1;7mTest AES encryption and decryption (GCM mode) \27[0m')
|
||||
local key = crypto.generatekeypair('aes',256)
|
||||
local key = crypto.generatekeypair('aes', 256)
|
||||
local plaintext = "Hello, AES GCM!"
|
||||
|
||||
-- Encrypt without providing IV (should auto-generate IV)
|
||||
print('\27[1mAES encryption (auto IV)\27[0m')
|
||||
local encrypted, iv, tag = crypto.encrypt("aes", key, plaintext, nil, "gcm")
|
||||
assert_equal(type(encrypted), "string", "AES encryption (GCM, auto IV)")
|
||||
assert_equal(type(iv), "string", "AES IV (auto-generated, GCM)")
|
||||
assert_equal(type(tag), "string", "AES GCM tag (auto IV)")
|
||||
assert_equal(#plaintext, #encrypted, "Ciphertext length matches plaintext")
|
||||
assert_equal(type(encrypted), "string", "Ciphertext type")
|
||||
assert_equal(type(iv), "string", "IV type")
|
||||
assert_equal(type(tag), "string", "Tag type")
|
||||
|
||||
-- Decrypt
|
||||
print('\n\27[1mAES decryption (auto IV)\27[0m')
|
||||
local decrypted = crypto.decrypt("aes", key, encrypted, iv, "gcm", nil, tag)
|
||||
assert_equal(decrypted, plaintext, "AES decryption (GCM, auto IV)")
|
||||
assert_equal(decrypted, plaintext, "Decrypted ciphertext matches plaintext")
|
||||
|
||||
-- Encrypt with explicit IV
|
||||
print('\n\27[1mAES encryption (explicit IV)\27[0m')
|
||||
local iv2 = GetRandomBytes(13) -- GCM IV/nonce can be 12-16 bytes, 12 is standard
|
||||
local encrypted2, iv_used, tag2 = crypto.encrypt("aes", key, plaintext, iv2, "gcm")
|
||||
assert_equal(type(encrypted2), "string", "AES encryption (GCM, explicit IV)")
|
||||
assert_equal(iv_used, iv2, "AES IV (explicit, GCM)")
|
||||
assert_equal(type(tag2), "string", "AES GCM tag (explicit IV)")
|
||||
assert_equal(type(encrypted2), "string", "Ciphertext type")
|
||||
assert_equal(iv_used, iv2, "IV match")
|
||||
assert_equal(type(tag2), "string", "Tag type")
|
||||
|
||||
print('\n\27[1mAES decryption (explicit IV)\27[0m')
|
||||
local decrypted2 = crypto.decrypt("aes", key, encrypted2, iv2, "gcm", nil, tag2)
|
||||
assert_equal(decrypted2, plaintext, "AES decryption (GCM, explicit IV)")
|
||||
assert_equal(decrypted2, plaintext, "Decrypted ciphertext matches plaintext")
|
||||
end
|
||||
|
||||
-- Test PemToJwk conversion
|
||||
|
@ -167,25 +174,25 @@ local function test_pem_to_jwk()
|
|||
local priv_key, pub_key = crypto.generatekeypair()
|
||||
print('\27[1mRSA Private key to JWK conversion\27[0m')
|
||||
local priv_jwk = crypto.convertPemToJwk(priv_key)
|
||||
assert_equal(type(priv_jwk), "table", "PEM to JWK conversion")
|
||||
assert_equal(priv_jwk.kty, "RSA", "JWK key type")
|
||||
assert_equal(type(priv_jwk), "table", "JWK type")
|
||||
assert_equal(priv_jwk.kty, "RSA", "kty is correct")
|
||||
|
||||
print('\n\27[1mRSA Public key to JWK conversion\27[0m')
|
||||
local pub_jwk = crypto.convertPemToJwk(pub_key)
|
||||
assert_equal(type(pub_jwk), "table", "PEM to JWK conversion")
|
||||
assert_equal(pub_jwk.kty, "RSA", "JWK key type")
|
||||
assert_equal(type(pub_jwk), "table", "JWK type")
|
||||
assert_equal(pub_jwk.kty, "RSA", "kty is correct")
|
||||
|
||||
-- Test ECDSA keys
|
||||
local priv_key, pub_key = crypto.generatekeypair('ecdsa')
|
||||
print('\n\27[1mECDSA Private key to JWK conversion\27[0m')
|
||||
local priv_jwk = crypto.convertPemToJwk(priv_key)
|
||||
assert_equal(type(priv_jwk), "table", "PEM to JWK conversion")
|
||||
assert_equal(priv_jwk.kty, "EC", "JWK key type")
|
||||
assert_equal(type(priv_jwk), "table", "JWK type")
|
||||
assert_equal(priv_jwk.kty, "EC", "kty is correct")
|
||||
|
||||
print('\n\27[1mECDSA Public key to JWK conversion\27[0m')
|
||||
local pub_jwk = crypto.convertPemToJwk(pub_key)
|
||||
assert_equal(type(pub_jwk), "table", "PEM to JWK conversion")
|
||||
assert_equal(pub_jwk.kty, "EC", "JWK key type")
|
||||
assert_equal(type(pub_jwk), "table", "JWK type")
|
||||
assert_equal(pub_jwk.kty, "EC", "kty is correct")
|
||||
end
|
||||
|
||||
-- Test CSR generation
|
||||
|
@ -194,24 +201,25 @@ local function test_csr_generation()
|
|||
local priv_key, _ = crypto.generatekeypair()
|
||||
local subject_name = "CN=example.com,O=Example Org,C=US"
|
||||
local san = "DNS:example.com, DNS:www.example.com, IP:192.168.1.1"
|
||||
assert(type(priv_key) == "string", "Private key type")
|
||||
|
||||
local csr = crypto.GenerateCsr(priv_key, subject_name)
|
||||
local csr = crypto.generateCsr(priv_key, subject_name)
|
||||
assert_equal(type(csr), "string", "CSR generation with subject name")
|
||||
|
||||
csr = crypto.GenerateCsr(priv_key, subject_name, san)
|
||||
csr = crypto.generateCsr(priv_key, subject_name, san)
|
||||
assert_equal(type(csr), "string", "CSR generation with subject name and san")
|
||||
|
||||
csr = crypto.GenerateCsr(priv_key, nil, san)
|
||||
csr = crypto.generateCsr(priv_key, nil, san)
|
||||
assert_equal(type(csr), "string", "CSR generation with nil subject name and san")
|
||||
|
||||
csr = crypto.GenerateCsr(priv_key, '', san)
|
||||
csr = crypto.generateCsr(priv_key, '', san)
|
||||
assert_equal(type(csr), "string", "CSR generation with empty subject name and san")
|
||||
|
||||
-- These should fail
|
||||
csr = crypto.GenerateCsr(priv_key, '')
|
||||
csr = crypto.generateCsr(priv_key, '')
|
||||
assert_not_equal(type(csr), "string", "CSR generation with empty subject name and no san is rejected")
|
||||
|
||||
csr = crypto.GenerateCsr(priv_key)
|
||||
csr = crypto.generateCsr(priv_key)
|
||||
assert_not_equal(type(csr), "string", "CSR generation with nil subject name and no san is rejected")
|
||||
end
|
||||
|
||||
|
@ -231,9 +239,9 @@ local function run_tests()
|
|||
test_csr_generation()
|
||||
print('')
|
||||
print("All tests passed!")
|
||||
EXIT=0
|
||||
EXIT = 0
|
||||
return EXIT
|
||||
end
|
||||
|
||||
EXIT=70
|
||||
EXIT = 70
|
||||
os.exit(run_tests())
|
||||
|
|
|
@ -8048,6 +8048,73 @@ kUrlPlus = nil
|
|||
---@type integer to transcode ISO-8859-1 input into UTF-8. See `ParseUrl`.
|
||||
kUrlLatin1 = nil
|
||||
|
||||
|
||||
--- This module provides cryptographic operations.
|
||||
|
||||
--- The crypto module for cryptographic operations
|
||||
crypto = {}
|
||||
|
||||
--- Converts a PEM-encoded key to JWK format
|
||||
---@param pem string PEM-encoded key
|
||||
---@return table?, string? JWK table or nil on error
|
||||
---@return string? error message
|
||||
function crypto.convertPemToJwk(pem) end
|
||||
|
||||
--- Generates a Certificate Signing Request (CSR)
|
||||
---@param key_pem string PEM-encoded private key
|
||||
---@param subject_name string? X.509 subject name
|
||||
---@param san_list string? Subject Alternative Names
|
||||
---@return string?, string? CSR in PEM format or nil on error and error message
|
||||
function crypto.generateCsr(key_pem, subject_name, san_list) end
|
||||
|
||||
--- Signs data using a private key
|
||||
---@param key_type string "rsa" or "ecdsa"
|
||||
---@param private_key string PEM-encoded private key
|
||||
---@param message string Data to sign
|
||||
---@param hash_algo string? Hash algorithm (default: SHA-256)
|
||||
---@return string?, string? Signature or nil on error and error message
|
||||
function crypto.sign(key_type, private_key, message, hash_algo) end
|
||||
|
||||
--- Verifies a signature
|
||||
---@param key_type string "rsa" or "ecdsa"
|
||||
---@param public_key string PEM-encoded public key
|
||||
---@param message string Original message
|
||||
---@param signature string Signature to verify
|
||||
---@param hash_algo string? Hash algorithm (default: SHA-256)
|
||||
---@return boolean?, string? True if valid or nil on error and error message
|
||||
function crypto.verify(key_type, public_key, message, signature, hash_algo) end
|
||||
|
||||
--- Encrypts data
|
||||
---@param cipher_type string "rsa" or "aes"
|
||||
---@param key string Public key or symmetric key
|
||||
---@param plaintext string Data to encrypt
|
||||
---@param mode string? AES mode: "cbc", "gcm", "ctr" (default: "cbc")
|
||||
---@param iv string? Initialization Vector for AES
|
||||
---@param aad string? Additional data for AES-GCM
|
||||
---@return string? Encrypted data or nil on error
|
||||
---@return string? IV or error message
|
||||
---@return string? Authentication tag for GCM mode
|
||||
function crypto.encrypt(cipher_type, key, plaintext, mode, iv, aad) end
|
||||
|
||||
--- Decrypts data
|
||||
---@param cipher_type string "rsa" or "aes"
|
||||
---@param key string Private key or symmetric key
|
||||
---@param ciphertext string Data to decrypt
|
||||
---@param iv string? Initialization Vector for AES
|
||||
---@param mode string? AES mode: "cbc", "gcm", "ctr" (default: "cbc")
|
||||
---@param tag string? Authentication tag for AES-GCM
|
||||
---@param aad string? Additional data for AES-GCM
|
||||
---@return string?, string? Decrypted data or nil on error and error message
|
||||
function crypto.decrypt(cipher_type, key, ciphertext, iv, mode, tag, aad) end
|
||||
|
||||
--- Generates cryptographic keys
|
||||
---@param key_type string? "rsa", "ecdsa", or "aes"
|
||||
---@param key_size_or_curve number|string? Key size or curve name
|
||||
---@return string? Private key or nil on error
|
||||
---@return string? Public key (nil for AES) or error message
|
||||
function crypto.generatekeypair(key_type, key_size_or_curve) end
|
||||
|
||||
|
||||
--[[
|
||||
────────────────────────────────────────────────────────────────────────────────
|
||||
LEGAL
|
||||
|
|
|
@ -1595,7 +1595,7 @@ static const luaL_Reg kLuaCrypto[] = {
|
|||
{"decrypt", LuaCryptoDecrypt}, //
|
||||
{"generatekeypair", LuaCryptoGenerateKeyPair}, //
|
||||
{"convertPemToJwk", LuaConvertPemToJwk}, //
|
||||
{"GenerateCsr", LuaGenerateCSR}, //
|
||||
{"generateCsr", LuaGenerateCSR}, //
|
||||
{0}, //
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue