add crypto library

This commit is contained in:
dagger 2026-08-22 10:50:08 +07:00 • committed by dagger
parent 2c6cffcf19
commit a23c4d4159
17 changed files with 2839 additions and 7 deletions

View file

@ -0,0 +1,140 @@
# *crypto* library
The library provides common cryptographic functions for mods
TLS and HTTP are not part of this library. They can use crypto for expensive
operations
Keys, signatures, hashes and encrypted data are passed as regular Lua strings.
Strings may contain zero bytes
The current API version is available in `crypto.API_VERSION`
## Hashing
```lua
crypto.sha256(data: str) -> str
crypto.sha384(data: str) -> str
crypto.sha512(data: str) -> str
crypto.md5(data: str) -> str
crypto.hash(hash: str, data: str) -> str
crypto.hmac(hash: str, key: str, data: str) -> str
```
Supported names are `SHA256`, `SHA384`, `SHA512` and `MD5`
MD5 is provided for old formats. SHA256 should be used for new data
Large data can be hashed in parts
```lua
local hash = crypto.hash_new("SHA256")
hash:update(part1)
hash:update(part2)
local result = hash:final()
```
Call `reset` before using the context again
## Signatures
```lua
crypto.ed25519_keypair() -> private_key, public_key
crypto.ed25519_public(private_key: str) -> str
crypto.ed25519_sign(private_key: str, message: str) -> str
crypto.ed25519_verify(public_key: str, message: str, signature: str)
-> true
-> false, error
crypto.ecdsa_keypair(curve: str) -> private_key, public_key
crypto.ecdsa_public(curve: str, private_key: str) -> str
crypto.ecdsa_sign(curve: str, private_key: str, message: str, hash: str) -> str
crypto.ecdsa_verify(curve: str, public_key: str, message: str,
signature: str, hash: str)
-> true
-> false, error
crypto.rsa_pkcs1_verify(hash: str, modulus: str, exponent: str,
message: str, signature: str)
-> true
-> false, error
crypto.rsa_pss_verify(hash: str, modulus: str, exponent: str,
message: str, signature: str, salt_length: int)
-> true
-> false, error
```
Ed25519 keys are 32 bytes and signatures are 64 bytes
ECDSA supports `P-256`, `P-384` and `P-521`. Public keys use the uncompressed
SEC1 format and signatures use DER
RSA modulus and exponent use big endian. A `salt_length` of `-1` uses the hash
size. RSA key generation is not provided, Ed25519 is easier for new keys
## Key exchange
```lua
crypto.x25519_keypair() -> private_key, public_key
crypto.x25519_public(private_key: str) -> str
crypto.x25519(private_key: str, peer_public_key: str) -> str
crypto.x25519_shared(private_key: str, peer_public_key: str) -> str
crypto.p256_keypair() -> private_key, public_key
crypto.p256_public(private_key: str) -> str
crypto.p256_shared(private_key: str, peer_public_key: str) -> str
```
`x25519` and `x25519_shared` do the same operation
Pass the shared secret through HKDF before using it as a key
## Encryption
```lua
crypto.aes_gcm_encrypt(key: str, nonce: str, aad: str, plaintext: str) -> str
crypto.aes_gcm_decrypt(key: str, nonce: str, aad: str, ciphertext: str)
-> plaintext
-> nil, error
crypto.chacha20_poly1305_encrypt(key: str, nonce: str, aad: str,
plaintext: str) -> str
crypto.chacha20_poly1305_decrypt(key: str, nonce: str, aad: str,
ciphertext: str)
-> plaintext
-> nil, error
```
AES GCM accepts 16 and 32 byte keys
ChaCha20 Poly1305 uses a 32 byte key and a 12 byte nonce
A 16 byte tag is appended to ciphertext. Decryption returns nothing when the
tag is invalid
Never use the same nonce twice with the same key
## Other functions
```lua
crypto.random_bytes(length: int) -> str
crypto.constant_time_equal(left: str, right: str) -> bool
crypto.hkdf_extract(hash: str, salt: str, ikm: str) -> str
crypto.hkdf_expand(hash: str, prk: str, info: str, length: int) -> str
crypto.pbkdf2(hash: str, password: str, salt: str,
iterations: int, length: int) -> str
crypto.scrypt(password: str, salt: str, n: int, r: int, p: int,
length: int, [optional]max_memory: int=0) -> str
crypto.features() -> table
```
Use scrypt or PBKDF2 with a random salt for passwords. A regular SHA256 hash is
not suitable for password storage
`features` returns the OpenSSL version and available functions
An invalid signature returns `false, "invalid_signature"`
An invalid encryption tag returns `nil, "authentication_failed"`
Invalid arguments raise a regular Lua error