Encryption Fundamentals

Encryption keeps secrets secret and detects when someone has tampered with data. The cryptographic primitives are mature and standardised; the way to ruin them is almost always at the application layer — wrong mode of operation, reused nonces, predictable IVs, hand-rolled key derivation.

This page is the working set: which primitive solves which problem, and the operational rules that distinguish "secure" from "looks secure."

Two big families

SymmetricAsymmetric
KeysOne shared secretPublic + private pair
SpeedFast (GBs/sec on commodity CPUs)Slow (KBs/sec for RSA, faster for ECC)
UseBulk data encryptionKey exchange, signatures, identity
ExamplesAES, ChaCha20RSA, ECDSA, ECDH

The standard composition: asymmetric to establish a shared symmetric key; symmetric to encrypt the actual data. TLS, Signal, every secure protocol does this. Asymmetric is too slow for bulk; symmetric needs a shared key, which asymmetric provides.

Symmetric encryption

AEAD ciphers

Modern symmetric encryption is AEAD (Authenticated Encryption with Associated Data). One operation provides confidentiality and integrity. Don't use older constructions (CBC mode + separate HMAC) for new code.

The two AEAD primitives that matter:

For new code: AES-GCM if hardware acceleration is available, ChaCha20-Poly1305 otherwise. Both are excellent.

Key sizes

Don't use AES-192. It's a strange middle that exists for historical reasons and isn't widely used; AES-128 or AES-256.

Nonce handling: where everyone trips

AEAD ciphers take a nonce (number used once) per encryption. Reusing a nonce with the same key destroys the security of GCM and CCM specifically. ChaCha20-Poly1305 too.

Three correct nonce strategies:

Nonce reuse is the single most common AEAD failure. Use a library that manages nonces correctly; don't hand-roll.

Modes you should not use

If you find yourself needing one of these, you almost certainly want AEAD instead.

Asymmetric encryption and signatures

RSA

The classic. Encryption / signing in the multiplicative group mod a 2048-bit (or larger) composite number.

In 2026, RSA persists for compatibility but ECC is preferred for new keys.

Elliptic-curve cryptography (ECC)

Same operations (encryption, signatures, key exchange) over an elliptic curve group. Smaller keys for equivalent security:

Faster, smaller, lower bandwidth. The default for new asymmetric crypto.

Curves to use:

Avoid:

Post-quantum

Shor's algorithm breaks RSA, ECDSA, and ECDH if a sufficiently large quantum computer exists. NIST standardised post-quantum algorithms in 2024:

For most teams: continue using RSA/ECC; watch for hybrid PQ-classical libraries to mature; plan migration over the next several years. For high-value or long-confidentiality (decades-from-now relevant) data, start adopting hybrid PQ where libraries support it now.

Hash functions

A hash maps arbitrary input to a fixed-length output, ideally with three properties:

The collision-resistance bound is roughly half the bit length: SHA-256 has 128-bit collision resistance.

In 2026:

Avoid: MD5 (broken since 2004), SHA-1 (collisions demonstrated in 2017), SHA-256 truncated to fewer than 128 bits (collision resistance drops below safe threshold).

What hashes are NOT for

Key derivation

Turn a password or a high-entropy secret into one or more cryptographic keys.

For passwords: Argon2id, with appropriate parameters (memory cost, time cost). Parameters tuned to make brute-force expensive while not crippling legitimate logins.

For derivation from already-strong secrets: HKDF (HMAC-based Key Derivation Function). Cheap, well-understood, the right choice for "I have a 256-bit secret; I need three 256-bit keys for different purposes."

For older code: PBKDF2 was the standard before Argon2; bcrypt is fine for password hashing if Argon2 isn't available.

Never:

Random number generation

CSPRNG — Cryptographically Secure Pseudo-Random Number Generator. Backed by the OS:

Language standard libraries usually wrap these:

Never use rand(), Math.random(), or any non-CSPRNG for cryptographic purposes. They're predictable; they're for simulations and games.

The "don't roll your own" rule

The most often-cited rule in cryptography. It means three different things:

  1. Don't invent your own primitives. Don't design a new cipher. The state of the art is the result of collective public review by professionals; your hobby cipher will lose.
  2. Don't reimplement existing primitives in production. Use libraries. Hand-rolled AES will leak side-channel information; the library version is constant-time.
  3. Don't combine primitives in non-standard ways. Don't invent your own protocol. Use TLS, Signal, age, libsodium constructions. Custom protocols mostly fail to subtle attacks.

What you can do:

Libraries that make doing the right thing easy:

A "what should I use for X" cheat sheet

NeedUse
Encrypt a file with a passwordage (age -p), or libsodium's crypto_secretstream with Argon2id key
Encrypt a payload with a known keyAES-GCM or ChaCha20-Poly1305, with a CSPRNG nonce
Encrypt for a known recipientage (age -r <recipient>), or libsodium's crypto_box
Sign dataEd25519 (crypto_sign_detached in libsodium)
Authenticate that data hasn't changedHMAC-SHA-256
Hash a password for storageArgon2id
Generate a session token256+ bits from CSPRNG; base64url-encode
Hash a file for integritySHA-256 or BLAKE3
Establish a shared key over insecure channelTLS 1.3 if it's a real network; libsodium's crypto_kx for in-app
Derive multiple keys from a masterHKDF-SHA-256

Further reading