Cryptography Best Practices for Developers

Chapter 1 · Practice 3 of 4

Know when to hash, encrypt, MAC or sign

From Choosing the right tool and library

Why it matters

Many bugs come from using the right algorithm for the wrong job, such as hashing a webhook body when you needed to prove who sent it. Pick by the property you need:

You needUseKeyExample
A fingerprint anyone can recomputehash (SHA-256, SHA-3, BLAKE2)nonefile checksums, content addressing
Secrecy and tamper detectionAEAD encryption (AES-GCM, ChaCha20-Poly1305)shared secret keyencrypting a field or a file
Proof a message came from someone holding a shared keyMAC (HMAC-SHA256)shared secret keywebhook signatures, signed cookies
Proof anyone can check, without sharing a secretdigital signature (Ed25519, ECDSA, ML-DSA)private key signs, public key verifiesrelease artifacts, JWTs verified by many services
Storing a password you only need to verifypassword hash (Argon2id)none, plus a saltuser passwords

A few rules fall out of the table:

  • A plain hash does not authenticate. Anyone can change the message and recompute it.
  • Encryption without authentication (AES-CBC or AES-CTR alone) lets attackers flip bits in the plaintext. Use an AEAD.
  • A MAC needs both sides to share the key, so any party that verifies can also forge. When many services verify, use signatures.
  • Passwords are not encrypted. OWASP's storage cheat sheet says passwords should not use reversible encryption. Sefism's Authentication Best Practices guide covers Argon2id parameters, so this guide does not repeat them.

Avoid

  • A bare SHA-256 of the body as a webhook "signature"
  • Encrypting passwords so they can be decrypted later
  • AES-CBC or AES-CTR without a MAC