Stop 13 · SecurityTopics · 10/12

Data Encryption

Part of the Backend Developer Roadmap

In short

Databases get dumped, laptops get stolen, Wi-Fi gets sniffed. Encryption makes sure that whatever leaks is unreadable junk without the key.

Protecting sensitive data both in transit (via HTTPS/TLS) and at rest (encrypting sensitive database fields) so a breach doesn't expose readable sensitive data.

The blob snaps a padlock shut on a steel trunk sitting on a railway platform trolley.

Think of it like this

The padlocked trunk on the train

Sending valuables by train? You lock the steel trunk before it leaves home and only the person with the key opens it at the other end. Even if a porter peeks or the trunk sits in a godown overnight, all anyone sees is a locked box.

Watch it happen

Two places data needs protecting

In transit

  • Data moving over a network
  • TLS (HTTPS) scrambles every packet
  • Stops snooping on Wi-Fi and proxies

At rest

  • Data sitting on disk or backups
  • Disk or field-level encryption, e.g. AES
  • Helps when a disk or dump leaks

You need both. Use HTTPS everywhere, turn on your database's disk encryption, and encrypt extra-sensitive fields like Aadhaar or bank numbers yourself.

The big ideas

What you need to know

The key is everything

Strong encryption with the key stored next to the data is theatre. Keep keys in a secret manager or KMS, away from the database.

Hashing is not encryption

Passwords should be hashed with bcrypt or argon2, which can't be reversed. Encryption is for data you need to read back.

Use authenticated modes

AES-256-GCM both hides data and detects tampering. Never invent your own cipher.

Fresh IV every time

Each encryption needs a new random IV (nonce). Reusing one with GCM can leak your data.

See it in code

Walk through the code

ts
1import { randomBytes, createCipheriv, createDecipheriv } from "node:crypto";2 3const key = Buffer.from(process.env.DATA_KEY!, "hex"); // 32 bytes4 5export function encrypt(text: string) {6  const iv = randomBytes(12);7  const cipher = createCipheriv("aes-256-gcm", key, iv);8  const data = Buffer.concat([cipher.update(text, "utf8"), cipher.final()]);9  return { iv, data, tag: cipher.getAuthTag() };10}11 12export function decrypt({ iv, data, tag }: { iv: Buffer; data: Buffer; tag: Buffer }) {13  const decipher = createDecipheriv("aes-256-gcm", key, iv);14  decipher.setAuthTag(tag);15  return Buffer.concat([decipher.update(data), decipher.final()]).toString("utf8");16}

1/4A 256-bit key from an env var, written as 64 hex characters. It never goes in the database.

Store iv, data and tag together (they aren't secret), but never the key. Make one with: node -e "console.log(crypto.randomBytes(32).toString('hex'))".

Save yourself the pain

Common mistakes

Oops

Encrypting passwords so you can 'show them to users later'.

Do this instead

Hash passwords with bcrypt or argon2. Nobody, not even you, should be able to read them back.

Oops

Hardcoding the encryption key in the source file.

Do this instead

Load it from a secret store or env var, and plan how you'd rotate it.

Your mission

Encrypt one sensitive column

~35 min

Quick check

Which of these should be hashed rather than encrypted?

Go deeper

  1. 1Confirm all your API traffic is served over HTTPS, never plain HTTP.
  2. 2Encrypt a genuinely sensitive field, e.g. a national ID number, before storing it.
  3. 3Learn the difference between encryption (reversible) and hashing (one-way) — use the right one for the right data.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge