mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-12 14:09:12 +00:00
All modes available on "tiny" builds
This commit is contained in:
parent
77ff5a24f9
commit
e7fc09b4a4
3 changed files with 194 additions and 103 deletions
|
@ -1,4 +1,3 @@
|
|||
---@diagnostic disable: lowercase-global
|
||||
-- Test RSA key pair generation
|
||||
local function test_rsa_keypair_generation()
|
||||
local priv_key, pub_key = crypto.generateKeyPair("rsa", 2048)
|
||||
|
@ -678,14 +677,14 @@ end
|
|||
local function run_tests()
|
||||
Log(kLogVerbose,"Testing RSA keypair generation...")
|
||||
test_rsa_keypair_generation()
|
||||
Log(kLogVerbose,"Testing RSA signing and verification...")
|
||||
test_rsa_signing_verification()
|
||||
Log(kLogVerbose,"Testing RSA-PSS signing and verification...")
|
||||
test_rsapss_signing_verification()
|
||||
Log(kLogVerbose,"Testing RSA encryption and decryption...")
|
||||
test_rsa_encryption_decryption()
|
||||
Log(kLogVerbose,"Testing RSA key size variations...")
|
||||
test_rsa_key_sizes()
|
||||
Log(kLogVerbose,"Testing RSA signing and verification...")
|
||||
test_rsa_signing_verification()
|
||||
Log(kLogVerbose,"Testing RSA encryption and decryption...")
|
||||
test_rsa_encryption_decryption()
|
||||
Log(kLogVerbose,"Testing RSA-PSS signing and verification...")
|
||||
test_rsapss_signing_verification()
|
||||
|
||||
Log(kLogVerbose,"Testing ECDSA keypair generation...")
|
||||
test_ecdsa_keypair_generation()
|
||||
|
@ -753,4 +752,5 @@ local function run_tests()
|
|||
end
|
||||
|
||||
EXIT = 70
|
||||
|
||||
os.exit(run_tests())
|
||||
|
|
|
@ -746,7 +746,7 @@ function EscapeHtml(str) end
|
|||
---@param path string?
|
||||
function LaunchBrowser(path) end
|
||||
|
||||
---@param ip uint32
|
||||
---@param ip integer|string
|
||||
---@return string # a string describing the IP address. This is currently Class A granular. It can tell you if traffic originated from private networks, ARIN, APNIC, DOD, etc.
|
||||
---@nodiscard
|
||||
function CategorizeIp(ip) end
|
||||
|
@ -1142,10 +1142,10 @@ function FormatHttpDateTime(seconds) end
|
|||
|
||||
--- Turns integer like `0x01020304` into a string like `"1.2.3.4"`. See also
|
||||
--- `ParseIp` for the inverse operation.
|
||||
---@param uint32 integer
|
||||
---@param ip integer
|
||||
---@return string
|
||||
---@nodiscard
|
||||
function FormatIp(uint32) end
|
||||
function FormatIp(ip) end
|
||||
|
||||
--- Returns client ip4 address and port, e.g. `0x01020304`,`31337` would represent
|
||||
--- `1.2.3.4:31337`. This is the same as `GetClientAddr` except it will use the
|
||||
|
@ -1363,25 +1363,25 @@ function HidePath(prefix) end
|
|||
---@nodiscard
|
||||
function IsHiddenPath(path) end
|
||||
|
||||
---@param uint32 integer
|
||||
---@param ip integer|string|string
|
||||
---@return boolean # `true` if IP address is not a private network (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`) and is not localhost (`127.0.0.0/8`).
|
||||
--- Note: we intentionally regard TEST-NET IPs as public.
|
||||
---@nodiscard
|
||||
function IsPublicIp(uint32) end
|
||||
function IsPublicIp(ip) end
|
||||
|
||||
---@param uint32 integer
|
||||
---@param ip integer|string|string
|
||||
---@return boolean # `true` if IP address is part of a private network (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16).
|
||||
---@nodiscard
|
||||
function IsPrivateIp(uint32) end
|
||||
function IsPrivateIp(ip) end
|
||||
|
||||
---@return boolean # `true` if the client IP address (returned by GetRemoteAddr) is part of the localhost network (127.0.0.0/8).
|
||||
---@nodiscard
|
||||
function IsLoopbackClient() end
|
||||
|
||||
---@param uint32 integer
|
||||
---@param ip integer|string|string
|
||||
---@return boolean # true if IP address is part of the localhost network (127.0.0.0/8).
|
||||
---@nodiscard
|
||||
function IsLoopbackIp(uint32) end
|
||||
function IsLoopbackIp(ip) end
|
||||
|
||||
---@param path string
|
||||
---@return boolean # `true` if ZIP artifact at path is stored on disk using DEFLATE compression.
|
||||
|
@ -1615,7 +1615,7 @@ function GetCryptoHash(name, payload, key) end
|
|||
--- to the system-configured DNS resolution service. Please note that in MODE=tiny
|
||||
--- the HOSTS.TXT and DNS resolution isn't included, and therefore an IP must be
|
||||
--- provided.
|
||||
---@param ip integer
|
||||
---@param ip integer|string|string
|
||||
---@overload fun(host:string)
|
||||
function ProgramAddr(ip) end
|
||||
|
||||
|
@ -1669,8 +1669,8 @@ function ProgramTimeout(milliseconds) end
|
|||
--- Hard-codes the port number on which to listen, which can be any number in the
|
||||
--- range `1..65535`, or alternatively `0` to ask the operating system to choose a
|
||||
--- port, which may be revealed later on by `GetServerAddr` or the `-z` flag to stdout.
|
||||
---@param uint16 integer
|
||||
function ProgramPort(uint16) end
|
||||
---@param port integer
|
||||
function ProgramPort(port) end
|
||||
|
||||
--- Sets the maximum HTTP message payload size in bytes. The
|
||||
--- default is very conservatively set to 65536 so this is
|
||||
|
@ -2169,7 +2169,7 @@ function bin(int) end
|
|||
--- unspecified format describing the error. Calls to this function may be wrapped
|
||||
--- in `assert()` if an exception is desired.
|
||||
---@param hostname string
|
||||
---@return uint32 ip uint32
|
||||
---@return string
|
||||
---@nodiscard
|
||||
---@overload fun(hostname: string): nil, error: string
|
||||
function ResolveIp(hostname) end
|
||||
|
@ -2183,7 +2183,7 @@ function ResolveIp(hostname) end
|
|||
--- The network interface addresses used by the host machine are always
|
||||
--- considered trustworthy, e.g. 127.0.0.1. This may change soon, if we
|
||||
--- decide to export a `GetHostIps()` API which queries your NIC devices.
|
||||
---@param ip integer
|
||||
---@param ip integer|string
|
||||
---@return boolean
|
||||
function IsTrustedIp(ip) end
|
||||
|
||||
|
@ -2213,7 +2213,7 @@ function IsTrustedIp(ip) end
|
|||
---
|
||||
--- Although you might want consider trusting redbean's open source
|
||||
--- freedom embracing solution to DDOS protection instead!
|
||||
---@param ip integer
|
||||
---@param ip integer|string
|
||||
---@param cidr integer?
|
||||
function ProgramTrustedIp(ip, cidr) end
|
||||
|
||||
|
@ -8051,85 +8051,70 @@ kUrlLatin1 = nil
|
|||
|
||||
--- This module provides cryptographic operations.
|
||||
|
||||
--- The crypto module for cryptographic operations
|
||||
crypto = {}
|
||||
|
||||
--- Signs a message using the specified key type.
|
||||
--- Supported types: "rsa", "rsa-pss", "ecdsa"
|
||||
---@param type "rsa"|"rsa-pss"|"rsapss"|"ecdsa"
|
||||
---@param key string PEM-encoded private key
|
||||
---@param message string
|
||||
---@param hash? string Hash algorithm ("sha256", "sha384", "sha512"). Default: "sha256"
|
||||
---@return string signature
|
||||
---@overload fun(type: string, key: string, message: string, hash?: string): nil, error: string
|
||||
function crypto.sign(type, key, message, hash) end
|
||||
--- 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
|
||||
|
||||
--- Verifies a signature using the specified key type.
|
||||
--- Supported types: "rsa", "rsa-pss", "ecdsa"
|
||||
---@param type "rsa"|"rsa-pss"|"rsapss"|"ecdsa"
|
||||
---@param key string PEM-encoded public key
|
||||
---@param message string
|
||||
---@param signature string
|
||||
---@param hash? string Hash algorithm ("sha256", "sha384", "sha512"). Default: "sha256"
|
||||
---@return boolean valid
|
||||
function crypto.verify(type, key, message, signature, hash) 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
|
||||
|
||||
--- Encrypts data using the specified cipher.
|
||||
--- Supported ciphers: "rsa", "aes"
|
||||
---@param cipher "rsa"|"aes"
|
||||
---@param key string PEM-encoded public key (RSA) or raw key (AES)
|
||||
---@param plaintext string
|
||||
---@param options? table Options for AES: { mode="cbc"|"gcm"|"ctr", iv=string, aad=string }
|
||||
---@return string ciphertext, string? iv, string? tag
|
||||
---@overload fun(cipher: string, key: string, plaintext: string, options?: table): nil, error: string
|
||||
function crypto.encrypt(cipher, key, plaintext, options) 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
|
||||
|
||||
--- Decrypts data using the specified cipher.
|
||||
--- Supported ciphers: "rsa", "aes"
|
||||
---@param cipher "rsa"|"aes"
|
||||
---@param key string PEM-encoded private key (RSA) or raw key (AES)
|
||||
---@param ciphertext string
|
||||
---@param options? table Options for AES: { mode="cbc"|"gcm"|"ctr", iv=string, tag=string, aad=string }
|
||||
---@return string plaintext
|
||||
---@overload fun(cipher: string, key: string, ciphertext: string, options?: table): nil, error: string
|
||||
function crypto.decrypt(cipher, key, ciphertext, options) 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
|
||||
|
||||
--- Generates a key pair.
|
||||
--- For RSA: bits = 2048 or 4096.
|
||||
--- For ECDSA: curve = "secp256r1", "secp384r1", "secp521r1", "curve25519"
|
||||
--- For AES: bits = 128, 192, or 256.
|
||||
---@param type "rsa"|"ecdsa"|"aes"
|
||||
---@param param? integer|string For RSA: bits; for ECDSA: curve name; for AES: bits
|
||||
---@return string private_key, string public_key|nil
|
||||
---@overload fun(type: string, param?: integer|string): nil, error: string
|
||||
function crypto.generateKeyPair(type, param) 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 options table Table with optional parameters:
|
||||
--- options.mode string? AES mode: "cbc", "gcm", "ctr" (default: "cbc")
|
||||
--- options.iv string? Initialization Vector for AES
|
||||
--- options.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, options) end
|
||||
|
||||
--- Converts a JWK (JSON Web Key, as a Lua table) to PEM format.
|
||||
---@param jwk table
|
||||
---@return string pem
|
||||
---@overload fun(jwk: table): nil, error: string
|
||||
function crypto.convertJwkToPem(jwk) 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 options table Table with optional parameters:
|
||||
--- options.iv string? Initialization Vector for AES
|
||||
--- options.mode string? AES mode: "cbc", "gcm", "ctr" (default: "cbc")
|
||||
--- options.tag string? Authentication tag for AES-GCM
|
||||
--- options.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, options) end
|
||||
|
||||
--- Converts a PEM key to JWK (JSON Web Key, as a Lua table).
|
||||
---@param pem string
|
||||
---@param claims? table Additional claims to merge (RFC7517 fields)
|
||||
---@return table jwk
|
||||
---@overload fun(pem: string, claims?: table): nil, error: string
|
||||
function crypto.convertPemToJwk(pem, claims) end
|
||||
|
||||
--- Generates a Certificate Signing Request (CSR) from a PEM key.
|
||||
---@param key string PEM-encoded private key
|
||||
---@param subject string Subject name (e.g., "CN=example.com")
|
||||
---@param sans? string Subject Alternative Names (SANs) as a comma-separated string
|
||||
---@return string csr_pem
|
||||
---@overload fun(key: string, subject: string, sans?: string): nil, error: string
|
||||
function crypto.generateCsr(key, subject, sans) end
|
||||
|
||||
-- AES options table for encrypt/decrypt:
|
||||
---@class CryptoAesOptions
|
||||
---@field mode? "cbc"|"gcm"|"ctr"
|
||||
---@field iv? string
|
||||
---@field tag? string
|
||||
---@field aad? string
|
||||
--- 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
|
||||
|
||||
|
||||
--[[
|
||||
|
|
|
@ -50,9 +50,7 @@ static const curve_map_t supported_curves[] = {
|
|||
{"P521", MBEDTLS_ECP_DP_SECP521R1}, //
|
||||
{"P-521", MBEDTLS_ECP_DP_SECP521R1}, //
|
||||
{"curve25519", MBEDTLS_ECP_DP_CURVE25519}, //
|
||||
#ifndef TINY
|
||||
{"curve448", MBEDTLS_ECP_DP_CURVE448}, //
|
||||
#endif
|
||||
{"curve448", MBEDTLS_ECP_DP_CURVE448}, //
|
||||
{NULL, 0}};
|
||||
|
||||
// List available curves
|
||||
|
@ -198,6 +196,24 @@ cleanup:
|
|||
return ret;
|
||||
}
|
||||
|
||||
// Ciphers
|
||||
typedef struct {
|
||||
const char *name;
|
||||
mbedtls_cipher_id_t id;
|
||||
} ciphers_map_t;
|
||||
|
||||
static const ciphers_map_t supported_ciphers[] = {
|
||||
{"AES-128-CBC", MBEDTLS_CIPHER_AES_128_CBC}, //
|
||||
{"AES-192-CBC", MBEDTLS_CIPHER_AES_192_CBC}, //
|
||||
{"AES-256-CBC", MBEDTLS_CIPHER_AES_256_CBC}, //
|
||||
{"AES-128-CTR", MBEDTLS_CIPHER_AES_128_CTR}, //
|
||||
{"AES-192-CTR", MBEDTLS_CIPHER_AES_192_CTR}, //
|
||||
{"AES-256-CTR", MBEDTLS_CIPHER_AES_256_CTR}, //
|
||||
{"AES-128-GCM", MBEDTLS_CIPHER_AES_128_GCM}, //
|
||||
{"AES-192-GCM", MBEDTLS_CIPHER_AES_192_GCM}, //
|
||||
{"AES-256-GCM", MBEDTLS_CIPHER_AES_256_GCM}, //
|
||||
{NULL, 0}};
|
||||
|
||||
// Strong RNG using mbedtls_entropy_context and mbedtls_ctr_drbg_context
|
||||
int GenerateRandom(void *ctx, unsigned char *output, size_t len) {
|
||||
static mbedtls_entropy_context entropy;
|
||||
|
@ -2350,14 +2366,10 @@ static int LuaCryptoSign(lua_State *L) {
|
|||
|
||||
if (strcasecmp(dtype, "rsa") == 0) {
|
||||
return LuaRSASign(L);
|
||||
}
|
||||
#ifndef TINY
|
||||
else if (strcasecmp(dtype, "rsa-pss") == 0 ||
|
||||
strcasecmp(dtype, "rsapss") == 0) {
|
||||
} else if (strcasecmp(dtype, "rsa-pss") == 0 ||
|
||||
strcasecmp(dtype, "rsapss") == 0) {
|
||||
return LuaRSAPSSSign(L);
|
||||
}
|
||||
#endif
|
||||
else if (strcasecmp(dtype, "ecdsa") == 0) {
|
||||
} else if (strcasecmp(dtype, "ecdsa") == 0) {
|
||||
return LuaECDSASign(L);
|
||||
} else {
|
||||
return luaL_error(L, "Unsupported signature type: %s", dtype);
|
||||
|
@ -2433,6 +2445,99 @@ static int LuaCryptoGenerateKeyPair(lua_State *L) {
|
|||
}
|
||||
}
|
||||
|
||||
// Returns a Lua table array of supported digests and ciphers (strings),
|
||||
// depending on the type argument:
|
||||
// "ciphers" - returns list of ciphers supported by crypto.encrypt and
|
||||
// crypto.decrypt "digests" - returns list of digests in supported_digests
|
||||
// "curves" - returns list of curves in supported_curves
|
||||
// If no argument is provided, returns a table with all three types
|
||||
static int LuaList(lua_State *L) {
|
||||
// Create a new table to hold the result
|
||||
lua_newtable(L);
|
||||
|
||||
// No argument provided - return all types in a structured table
|
||||
if (lua_isnoneornil(L, 1)) {
|
||||
// Create subtable for digests
|
||||
lua_pushstring(L, "digests");
|
||||
lua_newtable(L);
|
||||
const digest_map_t *digest = supported_digests;
|
||||
int i = 1;
|
||||
while (digest->name != NULL) {
|
||||
lua_pushstring(L, digest->name);
|
||||
lua_rawseti(L, -2, i++);
|
||||
digest++;
|
||||
}
|
||||
lua_settable(L, -3);
|
||||
|
||||
// Create subtable for curves
|
||||
lua_pushstring(L, "curves");
|
||||
lua_newtable(L);
|
||||
const curve_map_t *curve = supported_curves;
|
||||
i = 1;
|
||||
while (curve->name != NULL) {
|
||||
lua_pushstring(L, curve->name);
|
||||
lua_rawseti(L, -2, i++);
|
||||
curve++;
|
||||
}
|
||||
lua_settable(L, -3);
|
||||
|
||||
// Create subtable for ciphers
|
||||
lua_pushstring(L, "ciphers");
|
||||
lua_newtable(L);
|
||||
const ciphers_map_t *cipher = supported_ciphers;
|
||||
i = 1;
|
||||
while (cipher->name != NULL) {
|
||||
lua_pushstring(L, cipher->name);
|
||||
lua_rawseti(L, -2, i++);
|
||||
cipher++;
|
||||
}
|
||||
lua_settable(L, -3);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Argument provided - handle specific type
|
||||
const char *type = luaL_checkstring(L, 1);
|
||||
|
||||
if (strcasecmp(type, "curves") == 0) {
|
||||
// List all available curves
|
||||
const curve_map_t *curve = supported_curves;
|
||||
int i = 1;
|
||||
|
||||
while (curve->name != NULL) {
|
||||
lua_pushstring(L, curve->name);
|
||||
lua_rawseti(L, -2, i++);
|
||||
curve++;
|
||||
}
|
||||
} else if (strcasecmp(type, "digests") == 0) {
|
||||
// List all available digests
|
||||
const digest_map_t *digest = supported_digests;
|
||||
int i = 1;
|
||||
|
||||
while (digest->name != NULL) {
|
||||
lua_pushstring(L, digest->name);
|
||||
lua_rawseti(L, -2, i++);
|
||||
digest++;
|
||||
}
|
||||
} else if (strcasecmp(type, "ciphers") == 0) {
|
||||
// List all available ciphers
|
||||
const ciphers_map_t *cipher = supported_ciphers;
|
||||
int i = 1;
|
||||
|
||||
while (cipher->name != NULL) {
|
||||
lua_pushstring(L, cipher->name);
|
||||
lua_rawseti(L, -2, i++);
|
||||
cipher++;
|
||||
}
|
||||
} else {
|
||||
// Invalid type, return empty table
|
||||
lua_pushstring(L, "Invalid type. Use 'ciphers', 'digests', or 'curves'");
|
||||
lua_setfield(L, -2, "error");
|
||||
}
|
||||
|
||||
return 1; // Return the table
|
||||
}
|
||||
|
||||
static const luaL_Reg kLuaCrypto[] = {
|
||||
{"sign", LuaCryptoSign}, //
|
||||
{"verify", LuaCryptoVerify}, //
|
||||
|
@ -2442,6 +2547,7 @@ static const luaL_Reg kLuaCrypto[] = {
|
|||
{"convertJwkToPem", LuaConvertJwkToPem}, //
|
||||
{"convertPemToJwk", LuaConvertPemToJwk}, //
|
||||
{"generateCsr", LuaGenerateCSR}, //
|
||||
{"list", LuaList}, //
|
||||
{0}, //
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue