Skip to main content

Encryption at Rest vs In Transit — Two Different Threats

In transit (TLS) protects against interception on the wire. At rest (AES-256) protects against physical disk access or storage breach.

When to use

  • Always for PII, financial, health data
  • TLS for all service communication, including internal services (zero trust)

Tradeoffs

  • TLS 1.3 overhead is negligible; older TLS versions have cipher vulnerabilities
  • Encryption at rest doesn't protect a compromised application with DB access
ThreatAt RestIn Transit
Network eavesdroppingNoYes
Disk theft / storage breachYesNo
Compromised app with DB accessNoNo
Man-in-the-middleNoYes
// TLS server — enforce minimum TLS 1.2, prefer 1.3
tlsCfg := &tls.Config{
MinVersion: tls.VersionTLS12,
PreferServerCipherSuites: true,
}
srv := &http.Server{Addr: ":443", TLSConfig: tlsCfg}
srv.ListenAndServeTLS("cert.pem", "key.pem")

// AES-256-GCM encrypt
func encrypt(key, plaintext []byte) ([]byte, error) {
block, _ := aes.NewCipher(key) // key must be 32 bytes
gcm, _ := cipher.NewGCM(block)
nonce := make([]byte, gcm.NonceSize())
io.ReadFull(rand.Reader, nonce)
return gcm.Seal(nonce, nonce, plaintext, nil), nil
}

func decrypt(key, ciphertext []byte) ([]byte, error) {
block, _ := aes.NewCipher(key)
gcm, _ := cipher.NewGCM(block)
nonce, data := ciphertext[:gcm.NonceSize()], ciphertext[gcm.NonceSize():]
return gcm.Open(nil, nonce, data, nil)
}

Gotcha: Encrypting data at rest protects you from physical disk theft — not from an attacker with DB credentials. Access control is your first defense; encryption is your last.