~/learn / cryptography

Cryptography

The building blocks every security engineer needs, from encoding versus encryption to symmetric ciphers, hashing, and public key systems, what each primitive does and does not guarantee, and why nearly every real break is misuse rather than broken math.

beginnerupdated

Cryptography is everywhere you look as a practitioner: TLS on every site, password hashes in every database, signatures on every token, encrypted disks on every laptop. You do not need to be a mathematician to build or test systems that use it well. You need a precise mental model of what each primitive guarantees and, more importantly, what it does not, because the gap between those two is where real systems break.

Encoding, encryption, and hashing

These three are confused constantly, in code reviews and in bug reports, and the confusion is itself a finding.

Reversible? Needs a key? Purpose
Encoding (Base64, hex, URL encoding) Yes, by anyone No Represent data safely in another format
Encryption (AES, ChaCha20, RSA) Yes, with the key Yes Keep data confidential
Hashing (SHA-256, BLAKE2) No No Fingerprint data, detect change

If a “secret” is stored as Base64, it is not protected at all. Paste it into the encoder and it is plaintext. This is one of the most common real findings, and it usually means someone reached for the word “encode” when they needed “encrypt.”

The four properties

Every cryptographic design is assembling some mix of these four, and naming the one you actually need prevents most mistakes:

  • Confidentiality: only the intended party can read the data. Provided by encryption. Broken by: weak ciphers, ECB, nonce reuse.
  • Integrity: any change to the data is detected. Provided by MACs, signatures, and authenticated encryption. Broken by: encryption without a MAC, which lets an attacker flip bits in ciphertext and change the plaintext.
  • Authenticity: you know who produced the data. Provided by MACs (shared key) or signatures (public key). Broken by: trusting an unauthenticated channel, or a signature algorithm the attacker gets to choose.
  • Non-repudiation: the producer cannot later deny it. Only signatures provide this, because only one party holds the private key. A shared-key MAC cannot, because either holder could have produced the tag.

The single most common conceptual error is assuming encryption gives integrity. It does not. Plain AES-CBC or AES-CTR is perfectly confidential and completely malleable at the same time, which is why authenticated encryption exists and why it is the default you should reach for.

What to actually use

When in doubt, these are the safe defaults, and the rest of this section explains why:

  • Encrypt data: AES-256-GCM or ChaCha20-Poly1305 (authenticated encryption).
  • Hash for integrity: SHA-256, SHA-3, or BLAKE2.
  • Authenticate a message with a shared key: HMAC-SHA256.
  • Store passwords: Argon2id (or scrypt, bcrypt).
  • Random secrets: your platform CSPRNG, never Math.random.
  • Key exchange and signatures: X25519 and Ed25519, or P-256.

Kerckhoffs’s principle

A system should stay secure even if everything about it except the key is public. Custom “secret algorithms” violate this and nearly always fall apart the moment someone looks. When you meet homegrown crypto in a test, it deserves real attention; the cipher workbench breaks the classic constructions in seconds, which is a practical demonstration of why secrecy of design is not security.

Where this topic goes

The one rule

Do not design your own cryptography, and prefer high-level, well-reviewed libraries (libsodium, Tink, your platform’s standard library) over hand-assembling primitives. The algorithms are the part that already works. Your job is to wire them together without introducing the misuse that breaks them.

Go deeper