Mid-level 11 min · March 06, 2026

Encryption at Rest and in Transit

Comprehensive guide to data security: Master TLS/HTTPS for data in motion and AES-256 for data at rest.

N
Naren · Founder
Plain-English first. Then code. Then the interview question.
About
 ● Production Incident 🔎 Debug Guide
Quick Answer
  • Encryption in transit uses TLS (HTTPS) to protect data moving between client and server — no one intercepting the network can read it
  • Encryption at rest uses AES to protect stored data — no one with physical disk access can read it without the key
  • Both are necessary — transit encryption alone does not protect against database breaches, and rest encryption alone does not protect against man-in-the-middle attacks
  • Performance impact: TLS 1.3 adds ~5ms per handshake; AES-256 with AES-NI adds <1ms per field encryption
  • Biggest mistake: relying solely on TDE (transparent encryption) and neglecting application-level encryption for high-risk fields like SSNs or API keys
Plain-English First

Encryption scrambles your data so that only someone with the right key can unscramble it. Think of it like a locked box for your information. In transit encryption locks the box while it's being shipped across the internet. At rest encryption locks the box while it's sitting on a server or database. Both are needed because each protects against different kinds of theft.

In modern software architecture, 'secure by default' isn't just a catchphrase; it's a requirement. Encryption is the foundation of this security. Without transit encryption, any intermediary on the network—from a malicious Wi-Fi hotspot to a compromised ISP—can read your HTTP traffic in plaintext. Without rest encryption, a stolen database backup or a decommissioned hard drive exposes every user's PII (Personally Identifiable Information).

This guide moves beyond the theory. We will explore how TLS handshakes protect your packets in the wild and how to implement application-level encryption in Spring Boot to ensure that even if your database is fully compromised, your most sensitive fields remain indecipherable strings of noise. We'll also cover key management, compliance requirements, and the real production pitfalls engineers face when deploying encryption at scale.

Encryption in Transit — TLS/HTTPS

Encryption in transit ensures that data remains confidential and untampered while moving across the wire. Modern standards rely on TLS (Transport Layer Security) 1.2 or 1.3. When a client connects via HTTPS, a handshake occurs where the server proves its identity via a Certificate Authority (CA) and both parties negotiate a symmetric session key.

In a Spring Boot environment, you must ensure that your microservices don't just 'accept' HTTPS, but actively enforce it. This includes rejecting insecure algorithms (like SSLv3 or TLS 1.0) and ensuring that internal service-to-service communication is also encrypted, often managed via a Service Mesh like Istio or Linkerd.

TLS 1.3 reduces handshake latency to one round trip (0-RTT for resumption) and removes obsolete ciphers. In production, you should always prefer TLS 1.3 and enable HSTS to prevent SSL stripping attacks.

SecurityConfig.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package io.thecodeforge.security;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * Production-grade Security Configuration for io.thecodeforge
 * Forces HTTPS and sets Strict-Transport-Security (HSTS) headers.
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .requiresChannel()
            .anyRequest()
            .requiresSecure() // Redirects all HTTP traffic to HTTPS
            .and()
            .headers()
            .httpStrictTransportSecurity()
            .includeSubDomains(true)
            .maxAgeInSeconds(31536000); // 1 Year HSTS policy
    }
}

// Pro-Tip: When using RestTemplate or WebClient to call external APIs,
// never disable SSL verification. Use a proper TrustStore if dealing with
// private CA certificates.
How TLS Actually Protects Data
  • The server shows its ID (certificate) via a trusted CA — you wouldn't hand a briefcase to a stranger.
  • A symmetric session key is created using public-key cryptography (RSA or ECDHE) — the briefcase is locked with a shared secret.
  • All data after handshake is encrypted with that session key — only the two parties can open the briefcase.
  • TLS ensures integrity with MAC — if anyone tampers with the briefcase, the lock breaks and you know.
Production Insight
TLS termination at load balancer decrypts traffic inside your network.
Internal traffic between microservices often goes unencrypted — a single compromised pod can read all inter-service data.
Rule: always encrypt internal traffic with mutual TLS (mTLS) or a service mesh.
Key Takeaway
TLS protects data in motion.
Always enforce HTTPS and use the latest protocol version.
Internal traffic is not safe by default — encrypt it.
Choosing TLS Configuration for Your Services
IfExternal-facing API
UseEnforce TLS 1.3, HSTS, strong ciphers. Use a trusted CA certificate.
IfInternal microservice-to-microservice
UseUse mTLS with short-lived certificates. Service mesh (Istio) automates this.
IfLegacy system that doesn't support TLS 1.3
UseIsolate with network policies and a sidecar proxy that handles TLS upgrade.
IfDevelopment environment
UseUse self-signed certificates but ensure CI/CD does not propagate them to production.

TLS 1.2 vs TLS 1.3 Comparison

TLS 1.3, finalized in 2018, is a major overhaul over TLS 1.2. It reduces handshake latency, removes obsolete and insecure cipher suites, and introduces 0-RTT (zero round-trip time) resumption. The following table compares key properties:

PropertyTLS 1.2TLS 1.3
Handshake Round Trips2-RTT (full handshake)1-RTT (full handshake), 0-RTT for resumed sessions
Cipher SuitesMany combinations (RSA, DHE, ECDHE, AES-CBC, AES-GCM, ChaCha20)Only 5 AEAD suites (TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, etc.)
Key ExchangeRSA or Diffie-Hellman (DHE/ECDHE)Only Diffie-Hellman (ECDHE) — RSA key exchange removed
Forward SecrecyOptional (RSA key exchange does not provide it)Mandatory — all key exchanges provide forward secrecy
AuthenticationCertificate-basedCertificate-based, but signature algorithms are more restrictive
0-RTT ResumptionNot supportedSupported (with anti-replay protection)
Supported CurvesMany (limited by implementation)Only a few strong curves (P-256, P-384, P-521, X25519, X448)
CompressionSupported (but disabled in practice due to CRIME attack)Removed entirely
RenegotiationSupportedNot supported
Padding ExtensionNot definedDefined to prevent traffic analysis

In production, you should enforce TLS 1.3 wherever possible. If legacy clients require TLS 1.2, ensure you only enable the strongest cipher suites (ECDHE with AES-GCM). Disable TLS 1.0/1.1 and SSLv3 entirely.

Production Insight
Many cloud load balancers still default to supporting TLS 1.0/1.1 for backward compatibility. This is a common security gap. Always explicitly set the minimum TLS version to 1.2 in your infrastructure configuration (e.g., AWS ELB Security Policy, Azure Application Gateway).
Key Takeaway
TLS 1.3 is faster and more secure than TLS 1.2. Upgrade all services to TLS 1.3 and enforce minimum TLS 1.2.

Encryption at Rest — Database and File Storage

Encryption at rest protects data stored on persistent media. There are two primary levels: Transparent Data Encryption (TDE) and Application-Level Encryption. TDE, offered by AWS RDS or Azure SQL, encrypts the entire database file on the disk. However, if a user gains access to the database via an SQL injection, TDE won't help because the database engine decrypts data for the authorized process.

For high-stakes data (like SSNs or API keys), we use Application-Level Encryption. Here, the data is encrypted before it ever hits the database driver. Even a root-level database admin cannot see the raw values without access to the keys stored in an external Secrets Manager like AWS KMS or HashiCorp Vault.

When implementing field-level encryption, pay attention to IV generation and key rotation. AES-GCM is the recommended mode because it provides authenticated encryption — it detects if data has been tampered with.

EncryptionService.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package io.thecodeforge.security;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * Field-Level Encryption Utility
 * Standard: AES/GCM/NoPadding (Production recommended over ECB/CBC)
 */
public class EncryptionService {

    private static final String ALGORITHM = "AES/GCM/NoPadding";
    private static final int GCM_TAG_LENGTH = 128; // bits
    private static final int IV_LENGTH = 12; // bytes
    // In production, retrieve this key from AWS KMS or HashiCorp Vault
    private byte[] encryptionKey = System.getenv("DB_ENCRYPTION_KEY").getBytes();
    private SecureRandom secureRandom = new SecureRandom();

    public String encrypt(String data) throws Exception {
        SecretKeySpec secretKey = new SecretKeySpec(encryptionKey, "AES");
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        byte[] iv = new byte[IV_LENGTH];
        secureRandom.nextBytes(iv);
        GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, gcmSpec);
        byte[] cipherText = cipher.doFinal(data.getBytes());
        // Prepend IV to ciphertext for storage
        byte[] combined = new byte[IV_LENGTH + cipherText.length];
        System.arraycopy(iv, 0, combined, 0, IV_LENGTH);
        System.arraycopy(cipherText, 0, combined, IV_LENGTH, cipherText.length);
        return Base64.getEncoder().encodeToString(combined);
    }

    public String decrypt(String encryptedData) throws Exception {
        byte[] combined = Base64.getDecoder().decode(encryptedData);
        byte[] iv = new byte[IV_LENGTH];
        byte[] cipherText = new byte[combined.length - IV_LENGTH];
        System.arraycopy(combined, 0, iv, 0, IV_LENGTH);
        System.arraycopy(combined, IV_LENGTH, cipherText, 0, cipherText.length);
        SecretKeySpec secretKey = new SecretKeySpec(encryptionKey, "AES");
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, gcmSpec);
        return new String(cipher.doFinal(cipherText));
    }
}

// usage: entity.setSsn(encryptionService.encrypt(rawSsn));
// Store IV alongside ciphertext — it's not secret
AES-GCM IV Reuse Is Fatal
Never reuse the same IV (initialization vector) for two encryption operations with the same key. If the IV repeats, an attacker can XOR the ciphertexts to recover the plaintext. Always generate a new random IV for each encryption call. The IV is 12 bytes and can be stored alongside the ciphertext (it's not secret).
Production Insight
TDE gives false confidence — it only protects against physical theft.
Application-level encryption is your last line of defence against SQL injection and insider threats.
Rule: encrypt every sensitive field at the application layer; store keys outside the database.
Key Takeaway
Encryption at rest is not a single switch — choose the right layer.
TDE protects disks; app-level encryption protects data.
Never store keys near the data they protect.
Choosing Encryption Level for Different Data Types
IfEntire database disk needs protection
UseEnable TDE (AWS RDS encryption, SQL Server TDE, or LUKS for self-managed)
IfSpecific fields contain PII, credentials, or financial data
UseImplement application-level encryption with AES-GCM. Use a key management service.
IfData is archived to cold storage (S3 Glacier, tapes)
UseEncrypt the archive with envelope encryption (KMS key encrypts a data key, data key encrypts the files)
IfNeed to search or query encrypted data
UseConsider deterministic encryption (AES-SIV) or preserve some fields unencrypted (hashed). Avoid full searchability on sensitive data.

AES Encryption Modes Comparison (ECB, CBC, CTR, GCM)

AES operates on 128-bit blocks and can be used in different modes. The choice of mode dramatically affects security, performance, and features. Below is a comparison of the most common modes:

ModeSecurityIV Required?Authenticated?Parallelizable?Notes
ECBWeak — same plaintext block always encrypts to same ciphertext block. Leaks patterns.NoNoYesNever use ECB in production.
CBCSecure if IV is random and unpredictable. Vulnerable to padding oracle attacks if not combined with MAC.Yes (16 bytes)No (can add HMAC)No (sequential)Requires PKCS#7 padding. Must MAC after encrypt.
CTRSecure with unique IV/counter. No authentication. Parallel encryption and decryption.Yes (nonce + counter)NoYesStream cipher mode — no padding needed. Must ensure IV is never reused.
GCMSecure, provides authenticated encryption (confidentiality + integrity). Built-in MAC.Yes (12 bytes recommended)YesYes (encryption and authentication)The recommended mode for most applications. Hardware accelerated via AES-NI. Tag length 128 bits standard.

GCM is the gold standard for symmetric encryption in production. It combines AES-CTR with a cryptographic hash (GHASH) to provide integrity verification. Always use GCM with a 12-byte random IV and never reuse the IV with the same key. Avoid ECB entirely. CBC can be used if authenticated separately (e.g., CBC + HMAC), but GCM is simpler and more performant.

ECB Leaks Patterns — Never Use It
ECB mode encrypts each 16-byte block independently. This means identical plaintext blocks produce identical ciphertext blocks. For structured data like JSON, credit card numbers, or images, the patterns are visible in the ciphertext. A famous example is the 'ECB penguin' image — the outline of the penguin is clearly visible after encryption. ECB should be treated as broken for any real-world use.
Production Insight
Many legacy systems still use CBC mode because it was the default in older Java versions. If you must use CBC, ensure you add an HMAC after encryption (encrypt-then-MAC) to prevent padding oracle attacks. However, migrating to GCM is strongly recommended and typically a drop-in replacement with better security and hardware acceleration.
Key Takeaway
AES-GCM is the recommended encryption mode. It provides both confidentiality and integrity, is parallelizable, and has hardware support. Avoid ECB entirely and only use CBC with additional authentication.

Symmetric vs Asymmetric Encryption — Comparison

Encryption algorithms fall into two categories: symmetric (same key for encryption and decryption) and asymmetric (public/private key pair). Both are essential in modern cryptography. The table below contrasts them:

PropertySymmetric EncryptionAsymmetric Encryption
Key TypeSingle secret keyPublic key (encrypt) + Private key (decrypt)
SpeedVery fast (hardware accelerated)Slow (100-1000x slower than symmetric)
Key Size128–256 bits2048–4096 bits (RSA) or 256 bits (ECC)
Security Strength256-bit AES equivalent to 15360-bit RSAHeavily relies on mathematical hard problems (factorization, discrete log)
Use CasesBulk data encryption (files, database fields, TLS session data)Key exchange, digital signatures, certificate validation
Key DistributionMust securely share the secret keyPublic key can be freely distributed; private key kept secret
ExamplesAES, ChaCha20, TwofishRSA, ECDSA, Ed25519, Diffie-Hellman

In practice, systems combine both: asymmetric encryption (RSA or ECDH) is used to exchange a symmetric session key, and then symmetric encryption (AES-GCM) is used for the actual data. This is called a hybrid cryptosystem. For example, TLS uses ECDHE for key agreement (asymmetric) and AES-GCM for bulk encryption (symmetric). For encryption at rest, we use symmetric encryption (AES) directly, but the encryption key is often wrapped (asymmetrically) using a master key in a KMS.

Production Insight
Never encrypt large data with asymmetric encryption directly — it's extremely slow and the ciphertext size increases (RSA requires at least 42 bytes overhead per block). Always use envelope encryption: generate a random symmetric data key, encrypt the data with that, then encrypt the data key with an asymmetric key (or a KMS master key).
Key Takeaway
Symmetric encryption is fast and used for bulk data; asymmetric encryption is slow and used for key exchange and signatures. Production systems combine both for efficiency and security.

Key Management — The Hardest Part of Encryption

Encryption without proper key management is like locking a door and leaving the key in the lock. The security of your encrypted data ultimately rests on the secrecy and integrity of the encryption keys. This means you must never hardcode keys, never store them in the same database as the encrypted data, and never share them via email or chat.

Production-grade key management involves three principles: (1) Use a dedicated Hardware Security Module (HSM) or cloud Key Management Service (KMS) to generate, store, and rotate keys. (2) Implement key rotation policies — regularly generate new key versions and retire old ones. (3) Control access to keys with strict IAM policies and audit all usage.

Cloud providers offer managed KMS solutions (AWS KMS, Azure Key Vault, GCP Cloud KMS) that integrate seamlessly with their services. For multi-cloud or on-prem, HashiCorp Vault is a popular choice. A common pattern is envelope encryption: a master key (kept in the KMS) encrypts data keys, and the data keys encrypt your actual data. This allows efficient rotation of data keys without touching the encrypted payloads.

KmsService.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package io.thecodeforge.security;

import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.services.kms.KmsClient;
import software.amazon.awssdk.services.kms.model.*;

public class KmsService {

    private final KmsClient kmsClient;
    private final String keyId = System.getenv("KMS_KEY_ID");

    public KmsService() {
        this.kmsClient = KmsClient.builder().build();
    }

    public byte[] encryptData(byte[] plaintext) {
        EncryptRequest request = EncryptRequest.builder()
                .keyId(keyId)
                .plaintext(SdkBytes.fromByteArray(plaintext))
                .encryptionAlgorithm(EncryptionAlgorithmSpec.SYMMETRIC_DEFAULT)
                .build();
        EncryptResponse response = kmsClient.encrypt(request);
        return response.ciphertextBlob().asByteArray();
    }

    public byte[] decryptData(byte[] ciphertext) {
        DecryptRequest request = DecryptRequest.builder()
                .keyId(keyId)
                .ciphertextBlob(SdkBytes.fromByteArray(ciphertext))
                .encryptionAlgorithm(EncryptionAlgorithmSpec.SYMMETRIC_DEFAULT)
                .build();
        DecryptResponse response = kmsClient.decrypt(request);
        return response.plaintext().asByteArray();
    }
}

// Usage: KMS encrypts/decrypts app-level data keys, not the raw payload.
// Store encrypted data keys alongside ciphertext for envelope encryption.
Envelope Encryption Explained
In envelope encryption, a master key (stored in KMS/HSM) encrypts a data key. The data key encrypts your actual data. To decrypt, you first decrypt the data key using the master key, then use the data key to decrypt the data. This allows you to rotate the master key without re-encrypting all data — you only need to re-encrypt the data keys under the new master key.
Production Insight
Key rotation is often skipped because it's 'too complex'.
A leaked key that is not rotated exposes all data encrypted with that key — forever.
Rule: automate key rotation at least every 90 days; use envelope encryption to make rotation efficient.
Key Takeaway
Key management is harder than encryption itself.
Use a dedicated KMS or Vault.
Automate rotation and audit every key access.
Envelope encryption makes rotation practical.
Choosing a Key Management Approach
IfRunning on AWS
UseUse AWS KMS with envelope encryption. Enable automatic key rotation.
IfMulti-cloud or on-premises
UseUse HashiCorp Vault with an HSM backend. Integrate with Kubernetes (Vault CSI provider) for pod-level secrets.
IfStartup with low budget
UseUse cloud KMS free tier (AWS KMS, Azure Key Vault). Avoid self-managed HSMs unless compliance requires it.
IfCompliance requires FIPS 140-2 Level 3
UseUse a dedicated HSM (AWS CloudHSM, Azure Dedicated HSM). Ensure key generation and storage happen inside the HSM.

End-to-End Encryption (E2EE)

End-to-End Encryption ensures that data is encrypted on the sender's device and can only be decrypted on the intended recipient's device. No intermediary — including the server that facilitates the communication — can read the plaintext. This is different from TLS, which only protects data between the client and server; the server sees plaintext.

E2EE typically uses asymmetric encryption: each user has a public-private key pair. The sender encrypts the message with the recipient's public key, which can only be decrypted with the recipient's private key. In practice, for performance, a hybrid approach is used: a random symmetric key is encrypted with the recipient's public key, and the message is encrypted with that symmetric key.

Common applications include messaging apps (Signal, WhatsApp), email (PGP), and file sharing. Implementing E2EE in a web application is complex because the server never has access to the private keys — they must be stored client-side (e.g., in the browser's IndexedDB) and derived from a user password. This makes features like server-side search or server-side key rotation impossible without additional cryptographic techniques.

E2EE vs TLS: Not the Same
TLS protects data in transit between client and server, but the server sees plaintext. E2EE protects data from sender to recipient — the server is an untrusted intermediary. They serve different threat models. For many applications, TLS is sufficient; E2EE is required only when the service provider should not be able to read user content (e.g., messaging, cloud storage with zero-knowledge).
Production Insight
Implementing E2EE in a web app means you cannot reset passwords or recover keys on the server side. If a user loses their private key (or password-derived key), their data is permanently lost. This is a significant UX and support challenge. Must provide clear documentation and possibly a key backup mechanism (e.g., recovery codes that are themselves encrypted and stored server-side with the user's password hash).
Key Takeaway
E2EE ensures only the sender and recipient can read the data. Use asymmetric encryption for key exchange and symmetric encryption for the actual payload. The server must never have access to plaintext or private keys.

Application-Level Encryption Patterns in Spring Boot

Spring Boot applications often handle sensitive data that must be encrypted before persistence. A common approach is to create a JPA AttributeConverter that transparently encrypts and decrypts entity fields. This keeps encryption logic out of business code and ensures every read/write goes through encryption.

However, AttributeConverter has a significant gotcha: it runs inside the JPA transaction context. If encryption fails (e.g., KMS is unreachable), the entire transaction may roll back. Always handle encryption failures gracefully — consider storing an error marker or retrying with a fallback key. Also, note that AttributeConverter encrypts the column value, so any direct database queries or reports will see the ciphertext — you cannot query by plaintext directly without deterministic encryption.

For searchable encrypted fields, use deterministic encryption (AES-SIV) or a separate search index. Never use ECB mode. And remember: encrypting a field prevents indexing in most databases, so only encrypt fields that truly need it.

EncryptedAttributeConverter.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package io.thecodeforge.security;

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

@Converter
public class SsnAttributeConverter implements AttributeConverter<String, String> {

    private final EncryptionService encryptionService; // inject via Spring

    public SsnAttributeConverter(EncryptionService encryptionService) {
        this.encryptionService = encryptionService;
    }

    @Override
    public String convertToDatabaseColumn(String plainSsn) {
        if (plainSsn == null) return null;
        try {
            return encryptionService.encrypt(plainSsn);
        } catch (Exception e) {
            // Log error and rethrow as runtime exception to rollback transaction
            throw new RuntimeException("Encryption failed for SSN", e);
        }
    }

    @Override
    public String convertToEntityAttribute(String encryptedSsn) {
        if (encryptedSsn == null) return null;
        try {
            return encryptionService.decrypt(encryptedSsn);
        } catch (Exception e) {
            // Log error and return a placeholder or throw based on business needs
            throw new RuntimeException("Decryption failed for SSN", e);
        }
    }
}

// Usage in entity:
// @Convert(converter = SsnAttributeConverter.class)
// @Column(name = "ssn")
// private String ssn;
Handling Encryption Failures Gracefully
When KMS is down, your application should not crash. Consider implementing a circuit breaker for KMS calls and fallback to a local key cache. For reads, if decryption fails, return a masked value (e.g., '--****') and log an alert. Never expose raw encryption errors to the client.
Production Insight
AttributeConverter can cause unexpected transaction timeouts if KMS has high latency.
Encrypting a column that is used in WHERE clauses breaks indexing.
Rule: only encrypt columns that are never filtered by plaintext; use deterministic encryption with caution.
Key Takeaway
AttributeConverter keeps encryption out of business logic.
But it adds latency and breaks queries.
Secure the weakest link: where encryption keys are stored and accessed.
Application-Level Encryption Strategy
IfField is frequently queried by plaintext value
UseDo not encrypt it. Consider hashing with salt for exact matches, or use a separate searchable index.
IfField is rarely queried but highly sensitive (e.g., SSN, credit card)
UseUse random IV per field (AES-GCM) for maximum security. Accept that direct queries are impossible.
IfNeed to detect duplicate values (e.g., email uniqueness)
UseUse deterministic encryption (AES-SIV). Store a hash of the email alongside to allow duplicate checks.
IfCompliance requires field-level encryption (e.g., PCI DSS)
UseImplement tokenization combined with encryption. Store encrypted token mapping in a separate vault.

Encryption Performance Considerations

Encryption adds CPU overhead and latency, but modern hardware mitigates most of the impact. Key factors:

AES-NI Hardware Acceleration Most modern x86-64 processors (Intel Core i5/i7, Xeon, AMD Ryzen) include AES-NI instructions that accelerate AES encryption. With AES-NI, AES-256-GCM encryption/decryption runs at line rate (~1GB/s per core) with negligible CPU cost. Without AES-NI, software-based AES is still fast but can be 5-10x slower. Always verify AES-NI is enabled in your cloud instance type (e.g., AWS C5/m5 series have AES-NI; T2/t3.micro may not).

TLS Handshake Cost Establishing a new TLS connection involves asymmetric cryptography (key exchange) which is CPU-intensive. TLS 1.3 reduces the handshake from 2-RTT to 1-RTT (full handshake) and supports 0-RTT for resumption. The actual CPU cost of a full TLS 1.3 handshake is around 0.5-1ms on modern hardware (ECDHE key exchange). However, network round trips dominate latency — typically 5-30ms for a full handshake. Connection reuse (keep-alive, session resumption) eliminates this overhead.

Application-Level Encryption Overhead Encrypting a single database field with AES-GCM takes roughly 0.5-1µs per 1KB on a modern CPU with AES-NI. For a single API call encrypting 10 fields, total latency is <10µs — negligible compared to database round trips. The bigger cost is network round trips to KMS if you decrypt every time. Caching decrypted data keys locally (with proper expiry) reduces this.

Performance Best Practices 1. Enable AES-NI: ensure your deployment uses instances with AES-NI support (check /proc/cpuinfo or sysctl machdep.cpu.features on macOS). 2. Use TLS 1.3 and session resumption to minimize handshake overhead. 3. Cache KMS-decrypted data keys in local memory (with TTL). 4. For bulk encryption, use streaming encryption (e.g., CipherInputStream) to avoid large memory allocations. 5. Profile encryption overhead before optimizing — often encryption is not the bottleneck.

Check AES-NI Support in Production
Run openssl speed -evp aes-256-gcm on a production server. If you see >500MB/s throughput, AES-NI is active. Rates below 50MB/s indicate software-only mode. Most cloud instances today enable AES-NI by default, but always verify in your environment.
Production Insight
The #1 perf issue with encryption in production is not CPU but architecture: decrypting every field on every read, even when the field is not used. Lazy decryption (only decrypt when accessed) and result set filtering can reduce the overhead significantly. Also, beware of large batch operations (e.g., nightly reports) that can saturate KMS quota.
Key Takeaway
Modern hardware makes encryption overhead negligible (~1µs per field). Focus on minimizing network round trips (KMS calls) and TLS handshakes rather than CPU cycles. Use connection pooling and session resumption.

Compliance and Standards — PCI DSS, HIPAA, GDPR

Encryption isn't just a technical decision — it's a compliance requirement. Regulations like PCI DSS, HIPAA, and GDPR mandate encryption of specific data types. For example, PCI DSS Requirement 3.4 requires rendering PAN (Primary Account Number) unreadable anywhere it is stored, which typically means encryption, truncation, or tokenization. HIPAA's Security Rule requires encryption of ePHI (electronic Protected Health Information) at rest and in transit.

Meeting compliance requires more than just turning on encryption. You must demonstrate control over key management, prove that encryption is properly configured, and maintain audit logs of all encryption operations. Many compliance frameworks also require annual penetration testing and vulnerability scans that verify encryption configurations.

The key takeaway: encryption for compliance is often about process as much as technology. You need documented policies, access controls, and regular reviews. Tools like AWS Artifact and Azure Compliance Manager help maintain documentation, but the implementation must be correct at the code level.

compliance-check.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Example AWS Config rule to check that S3 buckets enforce encryption at rest
Resources:
  S3BucketEncryption:
    Type: AWS::Config::ConfigRule
    Properties:
      Source:
        Owner: AWS
        SourceIdentifier: S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED
      Scope:
        ComplianceResourceTypes:
          - AWS::S3::Bucket
      InputParameters:
        # Enforce SSE-KMS with specific KMS key
        # allowedEncryptionOptions: SSE-KMS

# Azure Policy to require encryption at rest for storage accounts
# https://docs.microsoft.com/en-us/azure/governance/policy/samples/require-storage-account-encryption
Compliance Audits Find Encryption Gaps
An auditor will not just ask 'Is encryption enabled?' — they will ask 'Where are your keys stored? Who has access? Are they rotated? Is the encryption algorithm FIPS 140-2 validated? You need to have answers documented and automated. A common failure is that encryption is enabled but the key is stored in a plaintext file on the same server — that fails audit immediately.
Production Insight
Compliance is not security — it's a minimum bar.
Many compliant systems still get breached because encryption is poorly configured.
Rule: use compliance requirements as a starting point, not the end goal.
Key Takeaway
Compliance mandates encryption — but don't stop there.
Document every encryption decision.
Auditors check key management as hard as encryption itself.
Good encryption is invisible; bad encryption fails audits and exposes data.
Encryption Requirements by Regulation
IfHandling credit card data (PCI DSS)
UseEncrypt PAN at rest with AES-256. Use tokenization if possible. Comply with PCI DSS v4.0 requirements for key management.
IfHandling health information (HIPAA)
UseEncrypt ePHI at rest and in transit. Implement access controls and audit logs. Ensure encryption algorithms meet NIST standards.
IfHandling EU personal data (GDPR)
UseEncryption is one of the recommended 'appropriate technical measures'. Implement pseudonymisation where possible. Document your encryption practices.
IfFinancial services (SOX, SOC2)
UseEncrypt sensitive financial data. Implement strict key management and rotation. Annual SOC2 audit will test encryption controls.

Compliance Requirements Comparison Table

Regulations have specific but sometimes overlapping encryption requirements. The following table compares PCI DSS, HIPAA, and GDPR:

RequirementPCI DSS v4.0HIPAA Security RuleGDPR
Data ScopeCardholder data (PAN, CVV, track data)Electronic Protected Health Information (ePHI)Personal Data of EU residents
Encryption at RestRequired (AES-128+ or equivalent)Addressable (recommended with AES)Encouraged as 'appropriate technical measure'
Encryption in TransitRequired (TLS 1.2+ or equivalent)Required (TLS 1.2+ recommended)Required for processing personal data
Key ManagementStrict: key rotation, access control, dual controlAddressable: key management policiesDocumented security measures
Algorithm RequirementsApproved algorithms (FIPS 140-2)NIST-approved algorithmsNot specified but industry best practices
Audit RequirementsAnnual assessment, quarterly scansRisk analysis, periodic reviewsData Protection Impact Assessment (DPIA)
PenaltiesFines up to $500k per violationUp to $1.5M per violationUp to 4% of global annual turnover
Tokenization AlternativeAllowed for PAN storageNot typically usedNot specified

Practical implications: If you store credit card data, you must comply with PCI DSS — this means using AES-256 for rest, enforcing TLS 1.2+ for transit, and implementing strict key management with rotation. For healthcare, HIPAA's addressable encryption means you must evaluate and decide; in practice, all covered entities encrypt ePHI. GDPR does not prescribe specific algorithms but expects encryption as part of 'data protection by design'.

Overlap of Regulations
A single system may need to satisfy multiple regulations simultaneously. For example, a medical app that collects payments (HIPAA + PCI DSS) should encrypt all ePHI and PAN at rest. Always use the stricter requirement when regulations overlap — which is almost always AES-256 and TLS 1.2+. Document your choices thoroughly for auditors.
Production Insight
Most compliance failures are not due to lack of encryption but due to lack of process: undocumented key rotation, missing audit logs, or unpatched systems. Automate compliance checks (e.g., AWS Config rules, Azure Policy) to continuously verify encryption requirements.
Key Takeaway
PCI DSS, HIPAA, and GDPR all mandate encryption but differ in specificity. Use AES-256 and TLS 1.2+ as a baseline; document everything. Automate compliance checks to pass audits consistently.
● Production incidentPOST-MORTEMseverity: high

Missing Encryption at Rest Exposes 50 Million Records

Symptom
Database backup file was discovered on a public S3 bucket during a security audit. The file contained unencrypted personal data.
Assumption
The team assumed that because the database was behind a VPC, no external attacker could reach it. They also believed that 'encryption at rest' meant only disk-level encryption (TDE), which was enabled on the RDS instance. However, they had exported the data to a separate S3 bucket for analytics without encrypting the export.
Root cause
The export process did not apply any encryption. TDE only protects data on the disk — once the database engine reads it and writes it to a file, the data is in plaintext. The S3 bucket had a misconfigured ACL allowing public read access.
Fix
Implement application-level encryption for sensitive fields before export. Use AWS KMS to encrypt the S3 object at upload time. Enable S3 Block Public Access. Set up a lifecycle policy to automatically encrypt objects with SSE-KMS.
Key lesson
  • Disk-level encryption (TDE) does not protect data exported from the database.
  • Encrypt sensitive fields at the application layer before writing to any external storage.
  • Always assume that any export or backup is a potential leak — encrypt everything.
  • Use Infrastructure as Code to prevent misconfigured buckets — don't rely on manual checks.
Production debug guideCommon encryption failures and their root causes4 entries
Symptom · 01
Browser shows 'NET::ERR_CERT_AUTHORITY_INVALID'
Fix
Check if the certificate is issued by a trusted CA. Run openssl verify -CAfile ca-cert.pem server.pem. Verify the certificate chain is complete and not expired.
Symptom · 02
Spring Boot reports 'javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure'
Fix
Check enabled TLS protocols and cipher suites. On the server, ensure TLS 1.2 or 1.3 is enabled. On the client, verify the trust store contains the server's CA certificate.
Symptom · 03
Decryption of stored data returns garbled output or throws BadPaddingException
Fix
Verify that the encryption algorithm, key, and IV used for decryption match exactly what was used during encryption. Check for key rotation or migration issues. Confirm Base64 encoding/decoding is correct.
Symptom · 04
Application cannot connect to AWS KMS to retrieve key
Fix
Check IAM permissions. Verify the application role has kms:Decrypt on the specific key ARN. Check network connectivity — KMS endpoint must be reachable (NAT gateway or VPC endpoint).
★ Quick Debug Commands for Encryption IssuesRun these commands to diagnose TLS and encryption problems fast.
TLS handshake failure or certificate error
Immediate action
Test connectivity and certificate chain
Commands
openssl s_client -connect example.com:443 -servername example.com</code>
curl -vI https://example.com/ 2>&1 | grep -i ssl</code>
Fix now
Check certificate expiration with openssl x509 -in cert.pem -text -noout | grep -A2 Validity. Renew if expired.
Decryption fails in Java with BadPaddingException+
Immediate action
Check encryption parameters used
Commands
java -Djdk.tls.client.protocols=TLSv1.2 -jar app.jar 2>&1 | grep -i cipher</code>
openssl enc -aes-256-cbc -d -in encrypted.bin -out decrypted.txt -K <hex_key> -iv <hex_iv> 2>&1</code>
Fix now
If using AES/GCM, ensure the IV length is 12 bytes and the tag is appended. Use Java's built-in AES/GCM/NoPadding with a random IV.
Java SSLHandshakeException: handshake_failure+
Immediate action
Check supported protocols and ciphers
Commands
nmap --script ssl-enum-ciphers -p 443 example.com</code>
java -Djavax.net.debug=ssl:handshake -jar app.jar 2>&1 | grep -E 'cipher|protocol|handshake'</code>
Fix now
Update server configuration to enable TLS 1.2 or 1.3. Disable TLS 1.0/1.1 and SSLv3. Use strong cipher suites like TLS_AES_256_GCM_SHA384.
AWS KMS Decrypt call returns AccessDeniedException+
Immediate action
Check IAM policy and key policy
Commands
aws kms decrypt --ciphertext-blob fileb://encrypted.enc --key-id <key-id> --output text --query Plaintext | base64 --decode</code>
aws iam simulate-principal-policy --policy-source-arn arn:aws:iam::123456789012:role/MyAppRole --action-names kms:Decrypt --resource-arns arn:aws:kms:us-east-1:123456789012:key/my-key</code>
Fix now
Add kms:Decrypt permission to the application's IAM role for the specific key. Ensure the key policy grants access to the role.
Encryption at Rest vs. Encryption in Transit
PropertyEncryption at RestEncryption in Transit
Protects againstPhysical disk theft, backup leaks, unauthorized database accessNetwork eavesdropping, MITM attacks, packet sniffing
TechnologiesAES-256, TDE, BitLocker, LUKS, KMSTLS 1.2/1.3, HTTPS, mTLS, IPsec
Where encryption occursAt the storage layer or application layer before storageBetween client and server, or between services
Key managementMaster keys in KMS/HSM, data keys per file/fieldSession keys negotiated per connection; server certificates
Performance impactNegligible with AES-NI; adds ~1ms per field encryptInitial handshake adds ~5ms; subsequent data encrypted at wire speed
Common mistakeAssuming TDE is enough for sensitive fieldsLeaving internal traffic unencrypted

Key takeaways

1
Transit encryption (TLS) protects data moving across networks
it is non-negotiable for modern web apps.
2
Rest encryption (AES-256) protects stored data
it is your last line of defense against physical theft and snapshot leaks.
3
Key Management is harder than Encryption
Store keys in a dedicated Secrets Manager (AWS KMS, Vault) and never hardcode them.
4
HSTS (Strict-Transport-Security) should be enabled to prevent 'SSL Stripping' attacks where HTTPS is downgraded to HTTP.
5
Defense in Depth
Use TDE for the hardware layer and Field-Level encryption for highly sensitive PII.
6
Automate key rotation
a leaked key that is not rotated compromises all data encrypted with it.
7
Compliance mandates encryption but does not guarantee security
always implement at the application layer for sensitive fields.

Common mistakes to avoid

5 patterns
×

Hardcoding encryption keys in source code

Symptom
The encryption key is visible in version control, logs, or compiled binaries. An attacker who accesses the code repository can decrypt all data encrypted with that key.
Fix
Never store keys in code. Use environment variables, secrets managers (AWS Secrets Manager, HashiCorp Vault), or cloud KMS. Rotate keys regularly and restrict access with IAM.
×

Disabling SSL/TLS certificate verification in development and forgetting to re-enable in production

Symptom
SSLHandshakeException disappears but the application is vulnerable to MITM attacks. An attacker can intercept and modify traffic without detection.
Fix
Always verify certificates in production. Use a proper trust store for self-signed certificates in development. Add CI checks to ensure SSL verification is never disabled in production builds.
×

Using ECB mode for AES encryption

Symptom
Patterns in the plaintext are visible in the ciphertext. For example, encrypting images with ECB reveals the image outline. Or encrypting structured data (e.g., JSON blocks) leaks field boundaries.
Fix
Never use ECB. Use AES-GCM or AES-CBC with a random IV. GCM also provides authentication, preventing tampering. Ensure you generate a new IV for each encryption.
×

Not rotating encryption keys

Symptom
If a key is compromised (e.g., leaked via logs, ex-employee, or security incident), all data encrypted with that key becomes readable. Without rotation, there is no way to limit the blast radius.
Fix
Implement automated key rotation (at least every 90 days). Use envelope encryption so that rotating the master key does not require re-encrypting all data. Audit key rotations and notify security teams.
×

Assuming TDE protects against SQL injection

Symptom
An attacker exploits an SQL injection vulnerability and reads sensitive data in plaintext because the database engine decrypts data for authorized queries.
Fix
Use application-level encryption for sensitive fields. TDE does not protect against attacks that operate at the database query level. Additionally, implement proper input validation and parameterized queries to prevent SQL injection.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01SENIOR
Explain the 'Man-in-the-Middle' (MITM) attack and how TLS specifically p...
Q02JUNIOR
Compare Symmetric (AES) vs. Asymmetric (RSA/ECC) encryption. Which is ty...
Q03SENIOR
What are the security implications of disabling SSL certificate verifica...
Q04SENIOR
How would you implement 'Searchable Encryption' if a business requiremen...
Q05SENIOR
What is the difference between an Initialization Vector (IV) and a Secre...
Q01 of 05SENIOR

Explain the 'Man-in-the-Middle' (MITM) attack and how TLS specifically prevents it.

ANSWER
A MITM attack occurs when an attacker intercepts communication between two parties, reading and potentially modifying messages. TLS prevents this through certificate validation: the server presents a certificate signed by a trusted Certificate Authority (CA). The client verifies that the certificate is valid for the domain and has not been revoked. Additionally, TLS uses public-key cryptography to establish a shared secret, so even if the attacker intercepts the initial handshake, they cannot decrypt the traffic without the server's private key. Mutual TLS (mTLS) extends this by having the client also present a certificate, preventing impersonation on both sides.
FAQ · 5 QUESTIONS

Frequently Asked Questions

01
If I use HTTPS, do I still need database encryption?
02
What is the performance overhead of encrypting every database field?
03
What is key rotation and why is it important?
04
Can I use the same key for encryption at rest and in transit?
05
What is the difference between encryption and hashing?
🔥

That's Security. Mark it forged?

11 min read · try the examples if you haven't

Previous
CSRF and XSS Prevention
6 / 10 · Security
Next
What is Salting in Security? (Password Protection Explained)