Learn / Security
Encryption basics
Lesson 26 of 37 · 9 min read ·
Three different things people confuse
Encoding (base64, URL-encoding) — reversible by anyone, no key, no secrecy. It is a format, not protection. A base64 string is plaintext with extra steps.
Hashing — one-way. Same input always gives the same fixed-length output; you cannot reverse it. Used for integrity checks and password storage.
Encryption — two-way with a key. Used when you need the data back.
Getting these straight fixes most of the confusion.
Symmetric vs asymmetric
Symmetric (AES) — one key encrypts and decrypts. Fast, good for bulk data. The hard part is getting the key to the other party.
Asymmetric (RSA, elliptic curve) — a keypair. The public key encrypts, only the private key decrypts. Or, for signatures, the private key signs and anyone can verify with the public key. Solves key distribution; roughly a thousand times slower.
So real systems use both: asymmetric crypto to agree on a symmetric key, then symmetric crypto for the actual data. That is exactly what TLS does.
Hashing, and why passwords are different
For integrity — has this file changed? — you want a fast hash: SHA-256.
For passwords you want a deliberately slow one. If your database leaks, an attacker with SHA-256 hashes can try billions of guesses per second on a GPU. Every common password falls in minutes.
Password hashing needs three properties:
- Slow and tunable — argon2id (first choice), bcrypt or scrypt. You set a cost factor and raise it as hardware improves.
- Salted — a unique random value per password, stored alongside the hash. Without it, identical passwords produce identical hashes and one rainbow table cracks everyone at once. Modern libraries do this for you.
- Constant-time comparison — comparing with
==leaks information through timing. Use the library's verify function.
Never invent your own scheme. argon2.hash(password) and argon2.verify(hash, password) is the whole API, and it is correct.
How TLS certificates earn trust
The chain in five steps:
- Your browser ships with a set of root certificate authorities it trusts, embedded by the OS or browser vendor.
- A site's certificate is signed by an intermediate CA, whose certificate is signed by a root.
- The server presents its certificate and the intermediates during the handshake.
- The browser verifies the signature chain up to a trusted root, and checks the domain matches, the certificate is in date, and it has not been revoked.
- If it all holds, they negotiate a shared symmetric key (via Diffie-Hellman, which gives forward secrecy — recording today's traffic does not decrypt it later even if the private key leaks) and switch to fast symmetric encryption.
What a certificate proves is narrow but important: you are talking to whoever controls this domain, and nobody in between can read or alter it. It says nothing about that party being trustworthy — a phishing site can have a perfectly valid certificate.
This is also why clicking through a certificate warning is dangerous: it is the exact signal that someone may be in the middle.
Encryption at rest vs in transit
In transit — TLS. Non-negotiable, including between your own services inside a private network.
At rest — disk or database encryption. It protects against stolen disks and misplaced backups. It does not protect against an attacker who has application access, because the application decrypts transparently. For genuinely sensitive fields, encrypt at the application layer with a key from a KMS, so a database dump alone is not enough.
Gotchas
- Never use ECB mode. It leaks structure so visibly there is a famous penguin image demonstrating it. Use AES-GCM, which also gives you authentication.
- Never reuse a nonce/IV with the same key. With GCM this catastrophically breaks confidentiality.
- Encryption without authentication lets an attacker tamper undetected. Use authenticated modes.
Math.random()is not cryptographically secure. Usecrypto.randomBytes/crypto.getRandomValuesfor tokens.- Rotate keys, and design for rotation from the start — store a key id with the ciphertext.
Prove you know it
Answer three questions without looking: why is bcrypt preferable to SHA-256 for passwords, what does a TLS certificate actually prove, and why is database-level encryption at rest not sufficient protection against a compromised application? If any answer is fuzzy, reread that section.