NURL

Cryptography

A pure-NURL crypto and TLS stack, built on libc only.

NURL ships its own cryptography and TLS implementation. The implementation uses only NURL on top of libc. No OpenSSL, no libcrypto, no libssl. A binary that only uses this stack links libc (and libm) alone. All of it is under stdlib/std/.

What's implemented

AreaModulesNotes
Post-Quantummlkem (FIPS 203 ML-KEM-512/768/1024), mldsa (FIPS 204 ML-DSA-44/65/87), slhdsa (FIPS 205 SLH-DSA-SHAKE)pure-NURL lattice and stateless hash-based KEM and signatures
Hashes & XOFhash_sha256, hash_sha512, hash_sha3 (FIPS 202 SHA3-224/256/384/512, SHAKE128/256), hash_blake2b, hash_blake3, hash_sha1, hash_md5SHA-1 and MD5 are for legacy interop only, never for signatures
HMAC / KDFhkdf, pbkdf2, scrypt
AEADaes_gcm (AES-128/256-GCM), chacha20poly1305the TLS 1.3 and QUIC record ciphers
Classical ECDH / signaturesx25519, ed25519, ecdsa_p256 (P-256 + P-384), minisignp256_field is a dedicated constant-time field implementation for the P-256 secret path
RSArsa (PKCS#1 v1.5 verify, PSS verify + sign)built on the bigint module
X.509, PKCS & SSHx509, x509_gen, csr (PKCS#10), pkey (encrypted PKCS#8 v2), tls_verify, ssh, ssh_ed25519DER/PEM parsing, cert/CSR generation, chain/hostname/policy verification, and SSH keys/wire protocol
TLS & QUICtls (client 1.3 with hybrid X25519MLKEM768 by default, 1.2 fallback), tls_server (1.3), quic_crypto, quic_tlssupports both classical and ML-DSA certificates
Randomnessrandom (CSPRNG), rng (xoshiro256**)rng is explicitly not cryptographic — simulations only
Constant-time comparesubtlelength-independent secret comparison

Randomness

Every cryptographic draw — keys, nonces, salts, blinding factors — goes through one runtime bridge that selects the OS CSPRNG per platform (getrandom(2) on Linux, arc4random_buf on macOS, BCryptGenRandom on Windows). If a draw fails, the system panics. It does not silently fall back to predictable bytes. The xoshiro256** generator in std/rng.nu is a separate, non-cryptographic PRNG. The crypto and TLS code never uses it.

Correctness

Every primitive has a known-answer test that runs on every build, backed by 770+ Project Wycheproof vectors and NIST ACVP test suites (including FIPS 203 ML-KEM, FIPS 204 ML-DSA, FIPS 205 SLH-DSA, and FIPS 202 SHA-3). Interoperability tests check the stack against OpenSSL, curl, browsers, and the badssl.com negative test suite. ECDSA signing uses a deterministic nonce (RFC 6979), so a signature is reproducible and never reuses a nonce. This is independent of the random per-signature blinding factor for side-channel hardening.

Side-channel posture

Timing vs. power/EM side-channels

By construction, the elliptic-curve and symmetric primitives run in constant time. This includes operand timing. RSA's big-integer arithmetic has one residual: operand-dependent timing. Blinding covers this. Power/electromagnetic (DPA/template) side-channels are out of scope for the whole stack. You need hardware, not software, to defend against those.

TLS

tls_connect verifies the full certificate chain and hostname. You skip verification with a separate, explicitly named function (tls_connect_insecure). It is not a flag on tls_connect. The socket-layer tcp_connect_tls (and its _alpn and _full variants) takes the choice as an argument instead: a non-zero verify verifies, 0 encrypts without verifying. See Networking for the connection-level API.

Next

  • Networking — TLS, MQTT, and the socket layer this stack sits under.
  • The full trust model, KAT list, and what is explicitly out of scope is in docs/CRYPTO.md.

Last updated on

On this page