Skip to content

Hashing, encoding & randomness

A grab-bag of the cryptographic and byte-wrangling helpers real programs reach for: digests, message authentication, base64, and random numbers. They live under std::crypto, std::text, and std::rand / std::os.

Digests take Bytes and return Bytes:

let data = std::bytes::from_string("hello");
let key = std::bytes::from_string("secret");
let digest = std::crypto::sha256(data); // 32 bytes
let tag = std::crypto::hmac_sha256(key, data); // 32 bytes
let sum = std::crypto::crc32(data); // Int (IEEE 802.3 / zlib)
let digest512 = std::crypto::sha512(data); // 64 bytes
let tag512 = std::crypto::hmac_sha512(key, data); // 64 bytes

sha1 (20 bytes) is there too for legacy interop; reach for sha256 by default. The 64-bit-word SHA-512 siblings — sha512 / hmac_sha512 (64-byte) — are the same non-fallible shape, for services that sign requests with HMAC-SHA512. The hashes and crc32 are hand-rolled — no OpenSSL dependency.

Raw hash bytes aren’t printable, so encode one to show or transport it:

println(std::text::base64::encode(digest));
let enc = std::text::base64::encode(data); // Bytes -> String
let dec = std::text::base64::decode(enc); // String -> Bytes
let url = std::text::base64::url_encode(data); // URL-safe, unpadded

url_encode is RFC 4648 §5 (the -_ alphabet, no = padding) — the form JWTs, OAuth, and webhook signatures use. decode accepts both alphabets.

For JWT / API-request signing, std::crypto ships ECDSA over NIST P-256 with SHA-256 (the ES256 JWS algorithm), OpenSSL-backed:

// key: PEM EC private key (SEC1 or PKCS#8); message: Bytes
let sig = std::crypto::ecdsa_p256_sign(key, message) or raise;
// pubkey: PEM SPKI; sig: raw r‖s, 64 bytes (the JWS/COSE form)
let ok = std::crypto::ecdsa_p256_verify(pubkey, message, sig);

ecdsa_p256_sign has two faces: a bare call returns an empty Bytes on failure (check len(sig) == 0), and in an or context it is fallible(CryptoError), so or raise / or fail err / or handle(err) propagate a structured CryptoError { kind, detail } like any other error.

std::rand is a fast, non-cryptographic PRNG — fine for jitter, sampling, shuffling, game logic:

let roll = std::rand::next_int(6) + 1; // a die roll, [1, 6]

For anything security-sensitive (tokens, nonces, keys), use the CSPRNG instead:

let nonce = std::os::getrandom(16) or raise; // 16 random Bytes

Next: reading configuration — CLI & config.