std/publickey

Public-key cryptography: Ed25519 and X25519; ECDSA and ECDH on P-256 and P-384; RSA with PKCS#1 v1.5 and PSS signatures and OAEP encryption; and keys in PEM, DER (PKCS#8 and SubjectPublicKeyInfo), raw bytes, and JWK.

import "std/publickey"

PrivateKey key = generate_key("ed25519")?
bytes signature = key.sign(to_bytes("a release"))?
PublicKey public = key.public_key()
print(public.verify(to_bytes("a release"), signature))     // true
write_text("key.pem", key.pem())
PublicKey theirs = public_key_from_pem(read_text("theirs.pem"))?

The work is OpenSSL's libcrypto, 3.0 or later, and none of it is Cuarzo's own: a program that imports std/publickey (or std/jwt) links with it, as pkg-config finds libcrypto. Install it as the system has it: libssl-dev on Debian and Ubuntu, openssl-devel on Fedora, openssl@3 from Homebrew on macOS (with PKG_CONFIG_PATH set to its lib/pkgconfig), and mingw-w64-x86_64-openssl in MSYS2 on Windows. A key is a value: a private key holds its PKCS#8 DER, a public key its SubjectPublicKeyInfo DER, in der, with its kind.

Function or method Result
generate_key(kind, bits) a new key of one of KEY_KINDS: "ed25519", "x25519", "p256", "p384", or "rsa" of bits (3072)
private_key_from_pem(text), public_key_from_pem(text) a key from PEM: PRIVATE KEY, RSA PRIVATE KEY, EC PRIVATE KEY, PUBLIC KEY, or RSA PUBLIC KEY
private_key_from_der(der), public_key_from_der(der) a key from DER, of any of those forms
private_key_from_raw(kind, raw), public_key_from_raw(kind, raw) an Ed25519 or X25519 key from its 32 bytes
private_key_from_jwk(jwk), public_key_from_jwk(jwk) a key from a JWK (RFC 7517) of kty OKP, EC, or RSA
key.public_key() a private key's public key
key.sign(message, scheme), public.verify(message, signature, scheme) a signature, and its check: Ed25519, ECDSA with SHA-256 or SHA-384 (in DER, as X.509 and TLS have it), or RSA-PSS with SHA-256, unless scheme names another of SIGNATURE_SCHEMES
key.shared_secret(peer) the secret X25519 or ECDH gives with a peer's key of the same kind; make a key of it with hkdf
public.encrypt(data), key.decrypt(data) RSA-OAEP with SHA-256, for a few bytes such as a key; seal more with std/crypto
k.pem(), k.raw(), k.jwk() the key as PEM (PKCS#8 or SubjectPublicKeyInfo), as raw bytes (Ed25519 and X25519), and as a JWK
public.equals(other) whether two public keys are the same
sign_file(key, path, scheme), verify_file(public, path, signature, scheme) the signature of a file of any size, as update packages are signed: of its SHA-512 hash after a label of its own, so it is never taken for the signature of something else
ecdsa_raw(der, size), ecdsa_der(raw) an ECDSA signature in DER, and as JWS writes it: r and s of size bytes each

Every error is an ERROR of kind "invalid_key" (data that is not a key, or a key that cannot do what is asked, such as an X25519 key that signs) or "invalid_argument".