Nền tảng Mật mã họcCryptography Fundamentals
Thuộc bộ kiến thức DevSecOps Roadmap.
Tổng quan
Cryptography (mật mã học) là nền tảng toán học mà hầu như mọi security control khác trong DevSecOps đều dựa vào: TLS trên đường truyền, secrets khi lưu trữ (at rest), container image được ký (signed), password storage, VPN tunnel, code-signing, JWT — tất cả, ở một tầng nào đó, đều quy về một số ít primitive mật mã: symmetric cipher, asymmetric key pair, và cryptographic hash function. Bạn không cần phải là một nhà mật mã học để làm DevSecOps, nhưng bạn cần nhận ra primitive nào giải quyết vấn đề nào, biết algorithm và mode cụ thể nào hiện được coi là an toàn, và — quan trọng nhất — biết khi nào nên dừng lại và dùng một thư viện đã được kiểm chứng thay vì tự sáng chế ra một scheme của riêng mình.
Cryptography cung cấp bốn thuộc tính bảo mật riêng biệt, và cần chính xác về việc cơ chế nào thực sự mang lại thuộc tính nào:
| Thuộc tính | Ý nghĩa | Cơ chế điển hình |
|---|---|---|
| Confidentiality (Bảo mật) | Chỉ bên được phép mới đọc được dữ liệu | Encryption (symmetric/asymmetric) |
| Integrity (Toàn vẹn) | Dữ liệu không bị thay đổi, dù vô tình hay cố ý | Hashing, MAC, AEAD cipher |
| Authenticity (Xác thực nguồn gốc) | Dữ liệu thực sự đến từ người gửi được khẳng định | Digital signature, MAC |
| Non-repudiation (Chống chối bỏ) | Người gửi không thể sau đó phủ nhận đã gửi | Digital signature (không phải MAC thuần) |
Một sai lầm rất phổ biến là encrypt dữ liệu rồi mặc định rằng điều đó cũng bảo vệ integrity của nó. Encryption thuần (ví dụ AES chế độ CBC không kèm MAC) chỉ bảo vệ confidentiality — kẻ tấn công dù không đọc được plaintext vẫn có thể lật bit (bit-flip) hoặc cắt bớt ciphertext mà không bị phát hiện. Các thiết kế hiện đại dùng AEAD (Authenticated Encryption with Associated Data, ví dụ AES-GCM, ChaCha20-Poly1305) chính vì nó mang lại confidentiality và integrity/authenticity cùng lúc.
Trong bối cảnh DevSecOps, cryptography xuất hiện khắp pipeline: TLS giữa mọi service-to-service call, hashing cho artifact integrity và định danh Git object, signing cho container image (Cosign/Sigstore) và commit (GPG/Sigstore), envelope encryption cho secrets trong vault, và password hashing ở bất cứ đâu ứng dụng lưu credential. Nắm vững nền tảng một lần sẽ đem lại lợi ích trên tất cả các bề mặt đó.
Kiến thức nền tảng
Symmetric encryption
Symmetric encryption dùng một shared key cho cả encryption lẫn decryption. Chuẩn phổ biến nhất là AES (Advanced Encryption Standard), một block cipher hoạt động trên khối 128-bit với key 128/192/256-bit. AES nhanh (thường được tăng tốc phần cứng qua AES-NI trên CPU hiện đại) và là công cụ chủ lực cho encryption khối lượng dữ liệu lớn — disk encryption, database-at-rest encryption, VPN payload, và giai đoạn bulk-data của TLS.
AES là block cipher, nên cần mode of operation để encrypt dữ liệu dài hơn một block:
| Mode | Có integrity không? | Ghi chú |
|---|---|---|
| ECB | Không | Không bao giờ dùng — các block plaintext giống nhau sinh ra ciphertext giống nhau, lộ pattern |
| CBC | Không (cần HMAC riêng) | Cần padding, dễ bị padding-oracle attack nếu không xử lý cẩn thận |
| CTR | Không (cần HMAC riêng) | Biến block cipher thành stream cipher; có thể chạy song song (parallelizable) |
| GCM | Có (AEAD) | Mặc định của ngành hiện nay; kết hợp encryption chế độ CTR với authentication tag tích hợp sẵn |
Điểm yếu cốt lõi của symmetric encryption là key distribution. Nếu Alice và Bob muốn giao tiếp, cả hai cần cùng một secret key — nhưng làm sao đưa key đó đến bên kia qua một mạng có thể không an toàn, mà không bị kẻ tấn công chặn được? Đây chính xác là vấn đề mà asymmetric cryptography được phát minh ra để giải quyết, và đó là lý do các giao thức thực tế (TLS, Signal, SSH) dùng symmetric cipher cho bulk data nhưng dùng cơ chế asymmetric để thiết lập shared key ngay từ đầu.
Ví dụ — encrypt và decrypt một file bằng AES-256-GCM với OpenSSL:
# Sinh key 256-bit ngẫu nhiên và IV/nonce 96-bit (không bao giờ dùng lại nonce với cùng một key!)
openssl rand -hex 32 > aes.key
openssl rand -hex 12 > aes.iv
# Encrypt
openssl enc -aes-256-gcm \
-K "$(cat aes.key)" -iv "$(cat aes.iv)" \
-in plaintext.txt -out ciphertext.bin
# Decrypt (cần đúng key + IV)
openssl enc -d -aes-256-gcm \
-K "$(cat aes.key)" -iv "$(cat aes.iv)" \
-in ciphertext.bin -out decrypted.txt
Vấn đề key distribution trong ví dụ này rất rõ ràng: aes.key phải được chuyển đến bên decrypt bằng cách nào đó, và nếu bị chặn trong quá trình truyền, toàn bộ encryption trở nên vô nghĩa.
Asymmetric encryption
Asymmetric (public-key) cryptography dùng một cặp key liên kết với nhau về mặt toán học: public key, có thể chia sẻ cho bất kỳ ai, và private key, tuyệt đối không được rời khỏi quyền kiểm soát của chủ sở hữu. Dữ liệu được encrypt bằng public key chỉ có thể decrypt bằng private key tương ứng, và — quan trọng hơn — dữ liệu được ký (sign) bằng private key có thể được xác minh (verify) bởi bất kỳ ai có public key. Thuộc tính duy nhất này loại bỏ hoàn toàn vấn đề key distribution: bạn có thể công khai public key của mình, và bất kỳ ai cũng có thể dùng nó để gửi cho bạn thứ mà chỉ bạn mới đọc được, mà không cần bất kỳ shared secret nào trước đó.
Hai họ thuật toán chủ đạo:
| Algorithm | Kích thước key (mức bảo mật tương đương) | Tốc độ | Ghi chú |
|---|---|---|---|
| RSA | 2048–4096 bit | Chậm hơn, đặc biệt ở kích thước lớn | Dựa trên độ khó của việc phân tích số nguyên tố lớn (factoring); vẫn được triển khai rộng rãi nhất |
| ECC (Elliptic Curve Cryptography) | 256–384 bit (ví dụ P-256, X25519) | Nhanh hơn, key/signature nhỏ hơn | Dựa trên bài toán discrete logarithm trên đường cong elliptic; được ưu tiên cho TLS, SSH hiện đại, và mobile/IoT nơi kích thước key quan trọng |
Vì các phép toán asymmetric tốn kém về mặt tính toán (chậm hơn khoảng 100–1000 lần so với symmetric cipher với cùng lượng dữ liệu), chúng được dùng để encrypt lượng dữ liệu nhỏ — phổ biến nhất là một symmetric session key, chứ không phải bulk payload.
Cặp key asymmetric cũng cho phép digital signature, mang lại authenticity, integrity, và non-repudiation trong một cơ chế duy nhất: người ký hash message, encrypt hash đó bằng private key của mình, và bất kỳ ai có public key đều có thể decrypt hash đó rồi so sánh với hash của chính họ tính trên message. Nếu khớp, message được chứng minh là không bị thay đổi và chắc chắn đến từ chủ private key.
Ví dụ — tạo cặp key RSA, ký một file, và verify signature:
# Sinh RSA private key 2048-bit
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private.pem
# Suy ra public key
openssl pkey -in private.pem -pubout -out public.pem
# Ký file (digest SHA-256 + RSA signature)
openssl dgst -sha256 -sign private.pem -out file.sig artifact.tar.gz
# Verify bằng public key
openssl dgst -sha256 -verify public.pem -signature file.sig artifact.tar.gz
# → "Verified OK"
Chính pattern này — hash, sign bằng private key, verify bằng public key — là nền tảng của container image signing (Sigstore/Cosign), signed Git commit, code-signing certificate, và certificate chain của TLS.
Hybrid encryption (vì sao TLS dùng cả hai)
Không có riêng symmetric hay asymmetric encryption nào lý tưởng cho giao thức mạng: symmetric nhanh nhưng không có cách nào trao đổi key an toàn; asymmetric giải quyết được key exchange nhưng lại quá chậm để encrypt hàng megabyte traffic. Hybrid encryption kết hợp cả hai, và đó chính xác là cách TLS hoạt động:
- Client và server thực hiện key exchange (ở TLS 1.3, là ephemeral Diffie-Hellman trên đường cong elliptic — ECDHE) để thống nhất một shared secret mà không bao giờ truyền trực tiếp nó.
- Shared secret đó được dùng để derive symmetric session key (thông qua key-derivation function, HKDF trong TLS 1.3).
- Toàn bộ dữ liệu ứng dụng thực tế cho phần còn lại của phiên được encrypt bằng symmetric cipher nhanh (AES-GCM hoặc ChaCha20-Poly1305) dùng các session key đó.
Asymmetric cryptography (cặp key của certificate server) chỉ được dùng để xác thực danh tính server — chứng minh public key thực sự thuộc về domain — chứ không dùng để encrypt bulk data. Đây là lý do TLS handshake tương đối tốn kém (một vài phép toán asymmetric) nhưng luồng dữ liệu được encrypt sau đó lại rẻ (thuần túy throughput symmetric AES).
Cryptographic hashing
Một cryptographic hash function nhận input độ dài bất kỳ và cho ra output độ dài cố định (gọi là “digest” hay “hash”), với ba thuộc tính khiến nó hữu ích cho bảo mật:
- Deterministic — cùng input luôn cho ra cùng output.
- One-way (pre-image resistant) — cho trước một hash output, việc tìm ra bất kỳ input nào tạo ra nó là bất khả thi về mặt tính toán.
- Collision-resistant — bất khả thi về mặt tính toán để tìm ra hai input khác nhau cho cùng một output.
- Avalanche effect — thay đổi một bit input làm thay đổi khoảng một nửa số bit output, nên các input tương tự nhau không cho ra hash tương tự nhau.
SHA-256 (thuộc họ SHA-2) là mặc định hiện nay cho kiểm tra integrity nói chung, định danh Git object (SHA-256 trong Git mới, SHA-1 trong lịch sử), chữ ký certificate TLS, và blockchain. SHA-3 là một chuẩn mới hơn, khác biệt về cấu trúc (dựa trên Keccak), có sẵn như một lựa chọn thay thế khi cần đa dạng hóa thuật toán.
MD5 và SHA-1 đã bị phá vỡ về mặt mật mã học và không được dùng cho bất kỳ mục đích bảo mật nào:
- MD5 có collision attack thực tế từ năm 2004 (có thể tạo ra hai input khác nhau cho cùng một hash chỉ trong vài giây trên phần cứng thông thường).
- SHA-1 đã có một collision thực tế được chứng minh (tấn công “SHAttered”, Google/CWI 2017) và đã bị NIST deprecate cho mọi mục đích digital signature và certificate từ năm 2011, trình duyệt từ chối certificate dùng SHA-1 từ năm 2017.
Cả hai vẫn có thể xuất hiện trong bối cảnh không liên quan bảo mật (ví dụ checksum nhanh để phát hiện file bị hỏng ngẫu nhiên, không giả định có kẻ tấn công), nhưng không bao giờ dùng cho signature, certificate, password storage, hoặc kiểm tra integrity nơi kẻ tấn công có thể cố tình giả mạo collision.
Ví dụ — tính và so sánh hash bằng OpenSSL:
$ openssl dgst -sha256 artifact.tar.gz
SHA2-256(artifact.tar.gz)= 8f14e45fceea167a5a36dedd4bea2543f9a4b3d0e8f9d3f1a2b3c4d5e6f7089
$ openssl dgst -md5 artifact.tar.gz
MD5(artifact.tar.gz)= 5d41402abc4b2a76b9719d911017c592 # ổn để làm checksum, KHÔNG dùng cho bảo mật
$ openssl dgst -sha1 artifact.tar.gz
SHA1(artifact.tar.gz)= aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d # đã deprecated, không dùng
Một ứng dụng phổ biến của hashing trong CI/CD: xác minh artifact hoặc base image tải về khớp với digest đã biết là hợp lệ trước khi sử dụng (sha256sum -c checksums.txt, hoặc pull image theo digest — image@sha256:... — thay vì theo tag có thể thay đổi).
Password hashing: vì sao hash thông thường là công cụ sai
Đây là một trong những sai lầm phổ biến và hậu quả nghiêm trọng nhất trong application security: hash password bằng một hash tổng quát nhanh như SHA-256 (kể cả có salt) là không đủ. SHA-256 được thiết kế để nhanh — đó chính xác là điều bạn muốn cho checksum và signature, và chính xác là điều bạn không muốn cho password, vì kẻ tấn công có database password bị đánh cắp có thể tính hàng tỷ hash SHA-256 mỗi giây trên GPU, khiến brute-force và dictionary attack nhắm vào hash bị đánh cắp trở nên rẻ.
Password hashing đòi hỏi các thuật toán được thiết kế cố ý để chậm và tốn tài nguyên, có thể điều chỉnh (tunable) khi phần cứng ngày càng mạnh hơn:
| Algorithm | Cách tiếp cận | Ghi chú |
|---|---|---|
| bcrypt | CPU-hard, dựa trên Blowfish | Được hỗ trợ rộng rãi, đã kiểm chứng qua thời gian từ 1999; có giới hạn độ dài password 72 byte |
| scrypt | CPU-hard và memory-hard | Thiết kế để chống lại phần cứng bẻ khóa chuyên dụng (custom ASIC/GPU) thông qua chi phí bộ nhớ |
| Argon2 (khuyến nghị Argon2id) | CPU-hard và memory-hard, có thể tune | Người chiến thắng Password Hashing Competition 2015; mặc định được OWASP khuyến nghị hiện nay |
Hai khái niệm quan trọng bất kể bạn chọn algorithm nào:
- Salting: một giá trị ngẫu nhiên, duy nhất được lưu kèm mỗi hash và trộn vào input trước khi hash. Salting vô hiệu hóa rainbow-table attack được tính sẵn và đảm bảo hai user có cùng password sẽ có hash lưu trữ khác nhau. Cả ba algorithm trên đều tự động xử lý salting như một phần thiết kế — bạn không cần quản lý riêng.
- Work factor (cost parameter): một tham số có thể điều chỉnh (bcrypt gọi là “rounds,” Argon2 có tham số time/memory/parallelism) kiểm soát mức độ tốn kém của mỗi lần tính hash. Nên tune sao cho việc hash mất khoảng 200–500ms trên phần cứng production, và tăng dần theo thời gian khi phần cứng mạnh hơn — đây là biện pháp phòng thủ cốt lõi chống brute force.
# Ví dụ: hash Argon2id bằng CLI argon2 (minh họa, không phải OpenSSL — OpenSSL không hỗ trợ Argon2)
echo -n "correct horse battery staple" | argon2 "$(openssl rand -hex 16)" -id -t 3 -m 16 -p 4 -l 32 -e
Khuyến nghị hiện hành của OWASP (Password Storage Cheat Sheet 2024): ưu tiên Argon2id, dùng bcrypt nếu Argon2 không khả dụng, và scrypt như một lựa chọn thay thế khác — không bao giờ dùng riêng SHA-256/SHA-512/MD5, kể cả có salt.
TLS/SSL
TLS (Transport Layer Security; SSL là tiền thân đã deprecated — SSLv2/v3 và TLS 1.0/1.1 đều bị cấm bởi các chuẩn hiện đại) bảo mật dữ liệu khi truyền đi bằng đúng mô hình hybrid đã mô tả ở trên. Một cái nhìn đơn giản hóa về TLS 1.2 handshake:
Client Server
|------ ClientHello (cipher hỗ trợ, random) ------>|
|<----- ServerHello (cipher được chọn, random) -----|
|<----- Certificate (public key của server) ---------|
|<----- ServerKeyExchange, ServerHelloDone ----------|
|------ ClientKeyExchange (pre-master secret) ----->|
|------ ChangeCipherSpec, Finished ------------------>|
|<----- ChangeCipherSpec, Finished -------------------|
|======= Dữ liệu ứng dụng đã encrypt (symmetric) ======|
Vậy là hai round trip đầy đủ trước khi bất kỳ dữ liệu ứng dụng nào được truyền. TLS 1.3 (RFC 8446) là một thiết kế lại đáng kể:
- Rút gọn handshake xuống còn một round trip (1-RTT), và hỗ trợ resumption 0-RTT cho kết nối lặp lại (kèm cảnh báo về replay attack với các request không idempotent).
- Loại bỏ hoàn toàn hỗ trợ cho các primitive yếu/lỗi thời — không còn RSA key exchange (không có forward secrecy), không còn cipher chế độ CBC, không SHA-1, không RC4, không static Diffie-Hellman. Mọi handshake giờ đều có forward secrecy vì bắt buộc dùng ephemeral key exchange (ECDHE).
- Đơn giản hóa việc thương lượng cipher suite thành một danh sách ngắn, được chọn lọc (ví dụ
TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256) — tất cả đều là AEAD, tất cả đều forward-secret. - Encrypt nhiều phần hơn của chính handshake (certificate không còn được gửi ở dạng cleartext), cải thiện metadata privacy.
Forward secrecy đáng được nhấn mạnh riêng: nghĩa là ngay cả khi private key của server bị lộ trong tương lai, các session đã ghi lại trong quá khứ vẫn không thể decrypt được, vì symmetric key của mỗi session được derive từ một ephemeral key exchange không để lại secret nào có thể tái sử dụng. Đây là lý do TLS 1.3 bắt buộc ECDHE và các triển khai TLS 1.2 nên tắt static RSA key exchange.
Kiểm tra cấu hình TLS của một server đang chạy:
# Xem protocol version và cipher được negotiate
openssl s_client -connect example.com:443 -tls1_3 -brief
# Toàn bộ certificate chain
openssl s_client -connect example.com:443 -showcerts </dev/null 2>/dev/null
# Audit nhanh cipher/protocol (cần nmap kèm script ssl-enum-ciphers)
nmap --script ssl-enum-ciphers -p 443 example.com
“HTTPS everywhere” giờ là kỳ vọng mặc định, không còn là một bước hardening tùy chọn: trình duyệt gắn cờ HTTP thuần là “Not Secure,” HSTS (header Strict-Transport-Security) buộc trình duyệt chỉ kết nối qua HTTPS đến một domain (ngăn downgrade attack kiểu SSL-stripping), và CA tự động miễn phí (Let’s Encrypt qua ACME) đã xóa bỏ lý do lịch sử về chi phí/độ phức tạp cho việc không dùng TLS. Traffic service-to-service nội bộ trong một cluster (mTLS qua service mesh) ngày càng được áp dụng cùng tiêu chuẩn đó — “tin tưởng mạng nội bộ” không còn là mô hình bảo mật chấp nhận được (xem Zero Trust).
Giải mã (decode) một certificate
Một certificate public-key (X.509) gắn một public key với một danh tính, được ký bởi một Certificate Authority. Decode một certificate cho thấy cấu trúc trong thực tế:
$ openssl x509 -in cert.pem -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 04:a1:9e:...
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, O=Let's Encrypt, CN=R11
Validity
Not Before: Jan 10 00:00:00 2026 GMT
Not After : Apr 10 23:59:59 2026 GMT
Subject: CN=example.com
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
ASN1 OID: prime256v1
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Key Usage: critical
Digital Signature
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Alternative Name:
DNS:example.com, DNS:www.example.com
Authority Information Access:
OCSP - URI:http://r11.o.lencr.org
CA Issuers - URI:http://r11.i.lencr.org/
X509v3 CRL Distribution Points:
Full Name: URI:http://r11.c.lencr.org/91.crl
Signature Algorithm: sha256WithRSAEncryption
Các trường quan trọng cần biết:
- Issuer / Subject — ai ký certificate và certificate định danh cho ai.
- Validity — khoảng thời gian phát hành/hết hạn; certificate ngắn hạn (90 ngày, như Let’s Encrypt) giới hạn phạm vi ảnh hưởng nếu key bị lộ.
- Subject Alternative Name (SAN) — danh sách thực tế các hostname mà certificate hợp lệ; client hiện đại bỏ qua trường
CNcũ khi so khớp hostname. - Key Usage / Extended Key Usage — giới hạn mục đích sử dụng key (ví dụ server auth vs. client auth vs. code signing).
- Authority Information Access / CRL Distribution Points — nơi kiểm tra trạng thái revocation (OCSP responder, vị trí CRL).
PKI (Public Key Infrastructure)
PKI là hệ thống chính sách, vai trò, và hạ tầng quản lý việc phát hành, phân phối, và thu hồi (revoke) certificate để public key có thể được tin cậy ở quy mô lớn.
Certificate chain of trust:
Root CA (tự ký, offline, nằm trong trust store của OS/browser)
└── Intermediate CA (online, thực hiện việc ký hàng ngày)
└── Leaf/end-entity certificate (example.com)
Root CA được giữ offline và air-gapped chính vì đó là trust anchor tối thượng — nếu bị compromise, mọi certificate từng được phát hành dưới nó đều đáng ngờ. Intermediate mới là bên thực sự ký leaf certificate hàng ngày, nên khi intermediate bị compromise (đã từng xảy ra, ví dụ vụ DigiNotar năm 2011) có thể được xử lý bằng cách revoke intermediate đó, thay vì revoke root.
Vòng đời của certificate:
- Issuance (phát hành) — bên đăng ký sinh một cặp key và một CSR (Certificate Signing Request), CA xác minh quyền kiểm soát domain/organization (các mức xác thực DV/OV/EV), sau đó ký certificate.
- Renewal (gia hạn) — trước khi hết hạn, một certificate mới được phát hành; tự động hóa (giao thức ACME, cert-manager trong Kubernetes) đã khiến certificate ngắn hạn trở nên khả thi bằng cách xử lý renewal mà không cần can thiệp thủ công.
- Revocation (thu hồi) — nếu private key bị lộ hoặc certificate bị phát hành sai, nó phải được vô hiệu hóa trước khi hết hạn tự nhiên:
- CRL (Certificate Revocation List) — CA công bố một danh sách đã ký các serial number certificate bị revoke; client tải về và kiểm tra. Nhược điểm: danh sách có thể phình to, và đây là kiểm tra “soft-fail” ở hầu hết client (CRL offline thường bị bỏ qua).
- OCSP (Online Certificate Status Protocol) — client truy vấn CA theo thời gian thực về trạng thái của một certificate cụ thể. Nhanh và nhẹ hơn CRL, nhưng tạo ra một phụ thuộc trực tiếp (live dependency) vào CA (độ trễ, rò rỉ privacy, và một sự cố ngoài dự kiến trở thành rủi ro fail-open) — được giảm nhẹ bằng OCSP stapling, trong đó chính server lấy và cache OCSP response đã ký rồi trình bày nó trong quá trình TLS handshake, để client không cần liên hệ CA nữa.
Certificate pinning giúp một client cụ thể chống lại một sự cố PKI compromise rộng hơn: client hardcode (pin) certificate hoặc public key mong đợi (hoặc hash của nó) cho một service nhất định, và từ chối kết nối nếu certificate được trình bày không khớp — ngay cả khi nó vẫn được ký hợp lệ bởi một CA đáng tin cậy. Điều này bảo vệ trước trường hợp một CA bị compromise hoặc bị ép buộc phát hành một certificate giả mạo cho domain của bạn. Đánh đổi là sự mong manh về vận hành: pinning phải được cập nhật đồng bộ với việc xoay vòng (rotation) certificate, nếu không bạn sẽ tự khóa mình ra trong một lần gia hạn thông thường (nhiều sự cố lớn từng xảy ra chính vì lý do này). Thực tiễn hiện đại ưu tiên pin CA/intermediate hoặc dùng giám sát Expect-CT/Certificate Transparency thay vì pin leaf certificate một cách nghiêm ngặt, chính để giảm sự mong manh đó.
Thiết kế PKI và failover ở cấp doanh nghiệp:
- Nhiều CA / phân cấp nhiều tầng — các tổ chức lớn thường vận hành hệ thống phân cấp root + issuing CA nội bộ riêng (cho certificate service nội bộ, VPN, xác thực thiết bị) tách biệt với CA công khai dùng cho các service hướng internet, để một sự cố nội bộ không ảnh hưởng đến trust công khai và ngược lại.
- High availability — issuing CA (và OCSP responder) được triển khai dự phòng qua nhiều region/zone; nếu một CA không khả dụng, việc tự động renewal (cert-manager, ACME client) phải suy giảm một cách nhẹ nhàng (degrade gracefully) thay vì để service chạy với certificate đã hết hạn.
- Certificate ngắn hạn + tự động hóa — xu hướng hiện đại (SPIFFE/SPIRE, mTLS trong service mesh, certificate 90-ngày/6-ngày của Let’s Encrypt) là rút ngắn đáng kể vòng đời certificate và dựa vào tự động phát hành/xoay vòng thay vì quy trình thủ công và hạ tầng revocation, vì một certificate hết hạn trong vài giờ hoặc vài ngày giới hạn giá trị của việc đánh cắp key của nó.
- Disaster recovery — private key của root CA thường được giữ trong HSM, offline, kèm quy trình đã được tài liệu hóa và kiểm thử cho việc tái phát hành intermediate khẩn cấp nếu intermediate bị compromise.
Khái niệm chính
Key management
Quản lý key mật mã đúng cách thường khó hơn việc chọn đúng algorithm — và đây là nơi hầu hết các sự cố mật mã học trong thực tế thực sự xảy ra (hardcoded key, key bị commit vào source control, key không bao giờ được rotate, một key dùng cho tất cả mọi thứ).
- KMS (Key Management Service) — một service được quản lý hoặc tự vận hành (AWS KMS, GCP Cloud KMS/Cloud HSM, Azure Key Vault, HashiCorp Vault) sinh, lưu trữ, xoay vòng, và kiểm soát truy cập key mật mã, thường được backed bởi một HSM. Ứng dụng gọi KMS API để encrypt/decrypt hoặc yêu cầu data key — chúng không bao giờ thấy hay xử lý trực tiếp raw master key.
- HSM (Hardware Security Module) — một thiết bị phần cứng chuyên dụng, chống can thiệp (tamper-resistant), sinh và lưu trữ key sao cho private key material không bao giờ có thể được xuất ra dưới dạng plaintext, kể cả bởi quản trị viên; mọi phép toán mật mã diễn ra bên trong thiết bị. Đây là root of trust vật lý đứng sau hầu hết các dịch vụ KMS doanh nghiệp và root key của CA.
- Envelope encryption — pattern chuẩn để encrypt lượng lớn dữ liệu bằng key được KMS quản lý mà không cần gửi chính dữ liệu đó đến KMS: một master key (Key Encryption Key, KEK) do KMS quản lý encrypt một data key (Data Encryption Key, DEK) được sinh ngẫu nhiên; DEK (không phải KEK) encrypt dữ liệu thực tế cục bộ; DEK đã encrypt được lưu kèm dữ liệu đã encrypt. Để decrypt, ứng dụng gửi DEK đã encrypt đến KMS, nhận lại DEK dạng plaintext, và decrypt dữ liệu cục bộ. Điều này có nghĩa master key không bao giờ rời khỏi ranh giới KMS/HSM và bulk data không bao giờ phải gửi qua mạng để encrypt/decrypt.
- 01KMS / HSMMaster Key (KEK) nằm ở đây, không bao giờ rời đi
- encrypt/decrypt02Data Encryption Key (DEK)ngẫu nhiên, theo từng object/file
- encrypt/decrypt (cục bộ, nhanh, symmetric)03Dữ liệu thực tếpayload lớn
- Key rotation — định kỳ thay thế key (KEK theo lịch tính bằng tháng/năm; DEK thường xuyên hơn, đôi khi theo từng object) để giới hạn phạm vi ảnh hưởng của một sự cố compromise chưa được phát hiện và để đáp ứng yêu cầu compliance (PCI-DSS bắt buộc rotation key định kỳ). Rotation phải hỗ trợ decrypt dữ liệu đã encrypt dưới các phiên bản key cũ trong khi encrypt dữ liệu mới dưới phiên bản hiện tại — hầu hết sản phẩm KMS version hóa key một cách trong suốt vì lý do này.
- Secrets vs. keys — một phân biệt tinh tế nhưng quan trọng: một key là vật liệu mật mã được dùng trong một phép toán mật mã (encrypt/decrypt/sign/verify); một secret là bất kỳ giá trị nhạy cảm nào ứng dụng cần (API token, mật khẩu database, hoặc chính các key). Secrets manager (Vault, AWS Secrets Manager) xử lý vòng đời secret rộng hơn — sinh động (dynamic generation), leasing, và revocation credential — trong khi KMS quản lý cụ thể các key mật mã và các phép toán liên quan. Trong thực tế, hai thứ này thường được xếp lớp lên nhau: một secrets manager có thể tự nó được mở khóa/encrypt bằng một key từ KMS.
So sánh: symmetric vs. asymmetric vs. hashing
| Symmetric encryption | Asymmetric encryption | Hashing | |
|---|---|---|---|
| Mục đích | Confidentiality | Confidentiality, key exchange, digital signature | Integrity, authenticity (khi kết hợp với signing), xác minh password |
| Key | Một shared secret key | Cặp public/private key | Không cần key (hoặc key cho HMAC) |
| Đảo ngược được không? | Có (với key) | Có (với private key) | Không — one-way theo thiết kế |
| Tốc độ | Nhanh | Chậm (chậm hơn 100–1000 lần so với symmetric) | Nhanh (trừ password hash được thiết kế cố ý chậm) |
| Algorithm điển hình | AES-256-GCM, ChaCha20-Poly1305 | RSA-2048/4096, ECC (P-256, X25519) | SHA-256, SHA-3, BLAKE2; bcrypt/Argon2 cho password |
| Trường hợp sử dụng điển hình | Encrypt bulk data, disk/DB encryption, dữ liệu session TLS | Key exchange trong TLS handshake, certificate, ký code/commit | Checksum, Git object ID, digest cho digital signature, lưu trữ password |
Best Practices
- Không bao giờ tự sáng chế crypto (roll your own crypto). Không thiết kế thuật toán mới hay tự implement lại primitive từ một bài báo; dùng thư viện chuẩn, đã được review kỹ (OpenSSL/BoringSSL, libsodium, crypto API của platform) với API cấp cao, chống lạm dụng (misuse-resistant) khi có thể.
- Ưu tiên thư viện cấp cao, đã kiểm chứng thay vì primitive cấp thấp. Ưu tiên API kiểu libsodium/NaCl (
crypto_secretbox,crypto_box) hoặc thư viện crypto đã được audit của ngôn ngữ bạn dùng, thay vì tự lắp ráp AES + HMAC — những sai lầm tinh vi (ví dụ không verify MAC trước khi decrypt, timing side channel khi so sánh) chính là cách các implementation tưởng chừng đúng lại bị phá vỡ. - Luôn dùng AEAD cipher cho encryption (AES-GCM, ChaCha20-Poly1305) thay vì các mode không có authentication (CBC, CTR) đòi hỏi bạn tự gắn thêm MAC một cách chính xác.
- Không bao giờ dùng hash tổng quát nhanh cho password. Dùng Argon2id (ưu tiên), bcrypt, hoặc scrypt, với work factor được tune phù hợp, và để thư viện tự xử lý salting.
- Chỉ dùng randomness an toàn về mặt mật mã.
/dev/urandom,openssl rand, hoặc CSPRNG của ngôn ngữ bạn dùng (ví dụsecretscủa Python, không phảirandom;crypto.randomBytescủa Node, không phảiMath.random()) — randomness yếu hoặc dự đoán được đã từng phá vỡ các hệ thống thực tế (ví dụ lỗi PRNG của Debian OpenSSL năm 2008, việc sinh key yếu trên thiết bị IoT). - Không bao giờ hardcode key hoặc secret trong source code, file config, hay container image. Load chúng tại runtime từ KMS/secrets manager; scan repo để phát hiện key bị commit nhầm (gitleaks, trufflehog) như một CI gate.
- Bắt buộc forward secrecy — yêu cầu ECDHE key exchange trong cấu hình TLS và tắt static RSA key exchange cùng các phiên bản protocol lỗi thời (SSLv3, TLS 1.0/1.1).
- Rotate key theo lịch trình và sau bất kỳ nghi ngờ compromise nào, và thiết kế hệ thống sao cho rotation không cần downtime (version hóa key, hỗ trợ decrypt dưới cả key cũ lẫn mới trong giai đoạn chuyển tiếp).
- Ưu tiên certificate ngắn hạn và tự động phát hành/renewal (ACME, cert-manager, SPIFFE/SPIRE) thay vì certificate dài hạn quản lý thủ công.
- Pin một cách có chủ đích, không phải theo mặc định — certificate/public-key pinning mạnh mẽ nhưng rủi ro về vận hành; hiểu rõ kế hoạch rollover trước khi bật nó, và ưu tiên pin intermediate/CA hơn là leaf certificate.
- Validate certificate đúng cách trong code — kiểm tra toàn bộ chain, hostname (SAN, không chỉ CN), thời hạn, và trạng thái revocation; không bao giờ tắt certificate validation “tạm thời” (
verify=False,-k/--insecure) ngoài môi trường test cục bộ dùng một lần, và grep cấu hình CI/CD để tìm các flag này. - Coi các yêu cầu crypto do compliance đặt ra là mức sàn (floor), không phải mức trần (ceiling) — module đã validate FIPS 140-2/3, key rotation theo PCI-DSS, và các yêu cầu tương tự định nghĩa mức tối thiểu; căn chỉnh lựa chọn kiến trúc theo chúng ngay từ đầu thay vì chỉnh sửa lại sau.
- Log và monitor việc sử dụng key và thời hạn certificate — certificate hết hạn gây ra outage, và việc sử dụng key trái phép không bị phát hiện, đều là những sự cố phổ biến, có thể tránh được; cảnh báo sớm trước khi hết hạn (ví dụ 30/14/3 ngày).
Tài liệu tham khảo
- NIST SP 800-57: Recommendation for Key Management
- NIST FIPS 197: Advanced Encryption Standard (AES)
- RFC 8446 — The Transport Layer Security (TLS) Protocol Version 1.3
- OWASP Cryptographic Storage Cheat Sheet
- OWASP Password Storage Cheat Sheet
- OWASP Transport Layer Security Cheat Sheet
- NIST SP 800-52 Rev. 2: Guidelines for TLS Implementations
- RFC 6960 — Online Certificate Status Protocol (OCSP)
Chủ đề liên quan: Nền tảng Networking cho Bảo mật · Identity & Access Management · Secure Coding & Bảo mật ứng dụng Web
Part of the DevSecOps Roadmap knowledge base.
Overview
Cryptography is the mathematical foundation that every other security control in DevSecOps ultimately leans on: TLS on the wire, secrets at rest, signed container images, password storage, VPN tunnels, code-signing, and JWTs all reduce, at some layer, to a handful of cryptographic primitives — symmetric ciphers, asymmetric key pairs, and cryptographic hash functions. You do not need to be a cryptographer to work in DevSecOps, but you do need to recognize which primitive solves which problem, know which specific algorithms and modes are currently considered safe, and — most importantly — know when to stop and use a vetted library instead of inventing your own scheme.
Cryptography provides four distinct security properties, and it’s worth being precise about which one each mechanism actually gives you:
| Property | What it means | Typical mechanism |
|---|---|---|
| Confidentiality | Only authorized parties can read the data | Encryption (symmetric/asymmetric) |
| Integrity | Data has not been altered, accidentally or maliciously | Hashing, MACs, AEAD ciphers |
| Authenticity | The data really came from the claimed sender | Digital signatures, MACs |
| Non-repudiation | The sender cannot later deny having sent it | Digital signatures (not plain MACs) |
A very common mistake is to encrypt data and assume that also protects its integrity. Plain encryption (e.g., AES in CBC mode with no MAC) protects confidentiality only — an attacker who cannot read the plaintext can often still flip bits or truncate ciphertext undetected. Modern designs use AEAD (Authenticated Encryption with Associated Data, e.g., AES-GCM, ChaCha20-Poly1305) specifically because it delivers confidentiality and integrity/authenticity together.
In a DevSecOps context, cryptography shows up everywhere in the pipeline: TLS between every service-to-service call, hashing for artifact integrity and Git commit addressing, signing for container images (Cosign/Sigstore) and commits (GPG/Sigstore), envelope encryption for secrets in a vault, and password hashing wherever your application stores credentials. Getting the fundamentals right once pays off across all of those surfaces.
Fundamentals
Symmetric encryption
Symmetric encryption uses one shared secret key for both encryption and decryption. The dominant standard is AES (Advanced Encryption Standard), a block cipher operating on 128-bit blocks with 128/192/256-bit keys. AES is fast (often hardware-accelerated via AES-NI on modern CPUs) and is the workhorse for bulk data encryption — disk encryption, database-at-rest encryption, VPN payloads, and the bulk-data phase of TLS.
AES is a block cipher, so it needs a mode of operation to encrypt data longer than one block:
| Mode | Provides integrity? | Notes |
|---|---|---|
| ECB | No | Never use — identical plaintext blocks produce identical ciphertext blocks, leaking patterns |
| CBC | No (needs separate HMAC) | Requires padding, vulnerable to padding-oracle attacks if not handled carefully |
| CTR | No (needs separate HMAC) | Turns the block cipher into a stream cipher; parallelizable |
| GCM | Yes (AEAD) | Industry default today; combines CTR-mode encryption with a built-in authentication tag |
The core weakness of symmetric encryption is key distribution. If Alice and Bob want to communicate, they both need the same secret key — but how do you get that key to the other party over a network that might be hostile, without an attacker intercepting it? This is exactly the problem asymmetric cryptography was invented to solve, and it’s why real-world protocols (TLS, Signal, SSH) use symmetric ciphers for bulk data but asymmetric mechanisms to establish the shared key in the first place.
Example — encrypt and decrypt a file with AES-256-GCM using OpenSSL:
# Generate a random 256-bit key and a 96-bit IV/nonce (never reuse a nonce with the same key!)
openssl rand -hex 32 > aes.key
openssl rand -hex 12 > aes.iv
# Encrypt
openssl enc -aes-256-gcm \
-K "$(cat aes.key)" -iv "$(cat aes.iv)" \
-in plaintext.txt -out ciphertext.bin
# Decrypt (same key + IV required)
openssl enc -d -aes-256-gcm \
-K "$(cat aes.key)" -iv "$(cat aes.iv)" \
-in ciphertext.bin -out decrypted.txt
The key distribution problem in this example is obvious: aes.key has to reach the decrypting party somehow, and if it’s ever intercepted in transit, the encryption is worthless.
Asymmetric encryption
Asymmetric (public-key) cryptography uses a mathematically linked key pair: a public key, which can be shared with anyone, and a private key, which must never leave its owner’s control. Data encrypted with the public key can only be decrypted with the corresponding private key, and — critically — data signed with the private key can be verified by anyone holding the public key. This single property eliminates the key-distribution problem: you can publish your public key openly, and anyone can use it to send you something only you can read, without any prior shared secret.
The two dominant families:
| Algorithm | Key size (comparable security) | Speed | Notes |
|---|---|---|---|
| RSA | 2048–4096 bit | Slower, especially at larger sizes | Based on the difficulty of factoring large primes; still the most widely deployed |
| ECC (Elliptic Curve Cryptography) | 256–384 bit (e.g., P-256, X25519) | Faster, smaller keys/signatures | Based on the elliptic curve discrete logarithm problem; preferred for modern TLS, SSH, and mobile/IoT where key size matters |
Because asymmetric operations are computationally expensive (roughly 100–1000x slower than symmetric ciphers for equivalent data), they are used to encrypt small amounts of data — most commonly a symmetric session key, not the bulk payload itself.
Asymmetric key pairs also enable digital signatures, which give authenticity, integrity, and non-repudiation in one mechanism: the signer hashes the message, encrypts the hash with their private key, and anyone with the public key can decrypt that hash and compare it against their own hash of the message. If they match, the message is provably untampered and provably from the private-key holder.
Example — generate an RSA key pair, sign a file, and verify the signature:
# Generate a 2048-bit RSA private key
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private.pem
# Derive the public key
openssl pkey -in private.pem -pubout -out public.pem
# Sign a file (SHA-256 digest + RSA signature)
openssl dgst -sha256 -sign private.pem -out file.sig artifact.tar.gz
# Verify with the public key
openssl dgst -sha256 -verify public.pem -signature file.sig artifact.tar.gz
# → "Verified OK"
This exact pattern — hash, sign with a private key, verify with the public key — is what underlies container image signing (Sigstore/Cosign), signed Git commits, code-signing certificates, and TLS certificate chains.
Hybrid encryption (why TLS uses both)
Neither symmetric nor asymmetric encryption alone is ideal for network protocols: symmetric is fast but has no way to safely exchange keys; asymmetric solves key exchange but is far too slow to encrypt megabytes of traffic. Hybrid encryption combines both, and it’s exactly what TLS does:
- The client and server perform a key exchange (in TLS 1.3, an ephemeral Diffie-Hellman exchange over an elliptic curve — ECDHE) to agree on a shared secret without ever transmitting it directly.
- That shared secret is used to derive symmetric session keys (via a key-derivation function, HKDF in TLS 1.3).
- All actual application data for the rest of the session is encrypted with the fast symmetric cipher (AES-GCM or ChaCha20-Poly1305) using those session keys.
Asymmetric cryptography (the server’s certificate key pair) is used only to authenticate the server’s identity — proving the public key really belongs to the domain — not to encrypt the bulk data. This is why TLS handshakes are relatively expensive (a handful of asymmetric operations) but the encrypted data stream afterward is cheap (pure symmetric AES throughput).
Cryptographic hashing
A cryptographic hash function takes an arbitrary-length input and produces a fixed-length output (the “digest” or “hash”), with three properties that make it useful for security:
- Deterministic — the same input always produces the same output.
- One-way (pre-image resistant) — given a hash output, it is computationally infeasible to find any input that produces it.
- Collision-resistant — it is computationally infeasible to find two different inputs that produce the same output.
- Avalanche effect — changing a single bit of input changes roughly half the output bits, so similar inputs don’t produce similar hashes.
SHA-256 (part of the SHA-2 family) is the current default for general-purpose integrity checking, Git object addressing (SHA-256 in newer Git, SHA-1 historically), TLS certificate signatures, and blockchain. SHA-3 is a newer, structurally different standard (Keccak-based) available as an alternative when algorithm diversity is wanted.
MD5 and SHA-1 are cryptographically broken and must not be used for any security purpose:
- MD5 has practical collision attacks since 2004 (two different inputs producing the same hash can be constructed in seconds on commodity hardware).
- SHA-1 had a practical, demonstrated collision (the “SHAttered” attack, Google/CWI 2017) and is deprecated by NIST for all digital signature and certificate use since 2011, with browsers rejecting SHA-1 certificates since 2017.
Both may still appear in non-security contexts (e.g., a quick checksum for accidental file corruption where no adversary is assumed), but never for signatures, certificates, password storage, or integrity checks where an attacker might deliberately try to forge a collision.
Example — compute and compare hashes with OpenSSL:
$ openssl dgst -sha256 artifact.tar.gz
SHA2-256(artifact.tar.gz)= 8f14e45fceea167a5a36dedd4bea2543f9a4b3d0e8f9d3f1a2b3c4d5e6f7089
$ openssl dgst -md5 artifact.tar.gz
MD5(artifact.tar.gz)= 5d41402abc4b2a76b9719d911017c592 # fine as a checksum, NOT for security
$ openssl dgst -sha1 artifact.tar.gz
SHA1(artifact.tar.gz)= aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d # deprecated, do not use
A common CI/CD use of hashing: verifying that a downloaded artifact or base image matches a known-good digest before use (sha256sum -c checksums.txt, or pulling images by digest — image@sha256:... — instead of by mutable tag).
Password hashing: why generic hashes are the wrong tool
This is one of the most common and consequential mistakes in application security: hashing a password with a fast general-purpose hash like SHA-256 (even with a salt) is insufficient. SHA-256 is designed to be fast — that’s exactly what you want for checksums and signatures, and exactly what you don’t want for passwords, because an attacker with a stolen password database can compute billions of SHA-256 hashes per second on a GPU, making brute-force and dictionary attacks against stolen hashes cheap.
Password hashing requires algorithms deliberately designed to be slow and resource-intensive, tunable as hardware gets faster:
| Algorithm | Approach | Notes |
|---|---|---|
| bcrypt | CPU-hard, based on Blowfish | Widely supported, battle-tested since 1999; has a 72-byte password length limit |
| scrypt | CPU- and memory-hard | Designed to resist custom ASIC/GPU cracking hardware via memory cost |
| Argon2 (Argon2id recommended) | CPU- and memory-hard, tunable | Winner of the 2015 Password Hashing Competition; current OWASP-recommended default |
Two concepts that matter regardless of which algorithm you pick:
- Salting: a unique, random value stored alongside each hash and mixed into the input before hashing. Salting defeats precomputed rainbow-table attacks and ensures that two users with the same password get different stored hashes. All three algorithms above handle salting automatically as part of their design — you don’t manage it separately.
- Work factor (cost parameter): a tunable parameter (bcrypt’s “rounds,” Argon2’s time/memory/parallelism parameters) that controls how expensive each hash computation is. This should be tuned so hashing takes roughly 200–500ms on your production hardware, and increased over time as hardware gets faster — this is the core defense against brute force.
# Example: Argon2id hashing via the argon2 CLI (illustrative, not OpenSSL — OpenSSL has no Argon2 support)
echo -n "correct horse battery staple" | argon2 "$(openssl rand -hex 16)" -id -t 3 -m 16 -p 4 -l 32 -e
OWASP’s current guidance (2024 Password Storage Cheat Sheet): prefer Argon2id, fall back to bcrypt if Argon2 isn’t available, and scrypt as another alternative — never SHA-256/SHA-512/MD5 alone, even salted.
TLS/SSL
TLS (Transport Layer Security; SSL is its deprecated predecessor — SSLv2/v3 and TLS 1.0/1.1 are all now forbidden by modern standards) secures data in transit using exactly the hybrid model described above. A simplified view of the TLS 1.2 handshake:
Client Server
|------ ClientHello (supported ciphers, random) -->|
|<----- ServerHello (chosen cipher, random) --------|
|<----- Certificate (server's public key) ----------|
|<----- ServerKeyExchange, ServerHelloDone ----------|
|------ ClientKeyExchange (pre-master secret) ----->|
|------ ChangeCipherSpec, Finished ------------------>|
|<----- ChangeCipherSpec, Finished -------------------|
|======= Encrypted application data (symmetric) ======|
That’s two full round trips before any application data flows. TLS 1.3 (RFC 8446) is a substantial redesign that:
- Reduces the handshake to one round trip (1-RTT), and supports 0-RTT resumption for repeat connections (with replay-attack caveats for non-idempotent requests).
- Removes support for weak/legacy primitives entirely — no RSA key exchange (no forward secrecy), no CBC-mode ciphers, no SHA-1, no RC4, no static Diffie-Hellman. Every handshake now provides forward secrecy by mandating ephemeral key exchange (ECDHE).
- Simplifies cipher suite negotiation to a short, curated list (e.g.,
TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256) — all AEAD, all forward-secret. - Encrypts more of the handshake itself (certificates are no longer sent in the clear), improving metadata privacy.
Forward secrecy deserves a callout: it means that even if a server’s private key is compromised in the future, past recorded sessions cannot be decrypted, because each session’s symmetric keys were derived from an ephemeral key exchange that leaves no reusable secret behind. This is why TLS 1.3 mandates ECDHE and TLS 1.2 deployments should disable static RSA key exchange.
Inspecting a live server’s TLS configuration:
# See negotiated protocol version and cipher
openssl s_client -connect example.com:443 -tls1_3 -brief
# Full certificate chain
openssl s_client -connect example.com:443 -showcerts </dev/null 2>/dev/null
# Quick cipher/protocol audit (requires nmap with ssl-enum-ciphers script)
nmap --script ssl-enum-ciphers -p 443 example.com
“HTTPS everywhere” is now the baseline expectation, not an optional hardening step: browsers flag plain HTTP as “Not Secure,” HSTS (Strict-Transport-Security header) forces browsers to only ever connect via HTTPS to a domain (preventing SSL-stripping downgrade attacks), and free automated CAs (Let’s Encrypt via ACME) removed the historical cost/complexity excuse for not using TLS. Internal service-to-service traffic inside a cluster (mTLS via a service mesh) is increasingly held to the same standard — “trust the network” is no longer an acceptable security model (see Zero Trust).
Decoding a certificate
A public-key (X.509) certificate binds a public key to an identity, signed by a Certificate Authority. Decoding one shows the structure in practice:
$ openssl x509 -in cert.pem -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 04:a1:9e:...
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, O=Let's Encrypt, CN=R11
Validity
Not Before: Jan 10 00:00:00 2026 GMT
Not After : Apr 10 23:59:59 2026 GMT
Subject: CN=example.com
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
ASN1 OID: prime256v1
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Key Usage: critical
Digital Signature
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Alternative Name:
DNS:example.com, DNS:www.example.com
Authority Information Access:
OCSP - URI:http://r11.o.lencr.org
CA Issuers - URI:http://r11.i.lencr.org/
X509v3 CRL Distribution Points:
Full Name: URI:http://r11.c.lencr.org/91.crl
Signature Algorithm: sha256WithRSAEncryption
Key fields to know:
- Issuer / Subject — who signed the certificate and who it identifies.
- Validity — the issuance/expiration window; short-lived certs (90 days, as with Let’s Encrypt) limit the blast radius of a compromised key.
- Subject Alternative Name (SAN) — the actual list of hostnames the cert is valid for; modern clients ignore the legacy
CNfield for hostname matching. - Key Usage / Extended Key Usage — constrains what the key may be used for (e.g., server auth vs. client auth vs. code signing).
- Authority Information Access / CRL Distribution Points — where to check revocation status (OCSP responder, CRL location).
PKI (Public Key Infrastructure)
PKI is the system of policies, roles, and infrastructure that manages issuance, distribution, and revocation of certificates so that public keys can be trusted at scale.
Certificate chain of trust:
Root CA (self-signed, offline, in OS/browser trust store)
└── Intermediate CA (online, does day-to-day signing)
└── Leaf/end-entity certificate (example.com)
Root CAs are kept offline and air-gapped precisely because they are the ultimate trust anchor — if compromised, every certificate ever issued under them is suspect. Intermediates are the ones actually signing leaf certificates day to day, so an intermediate compromise (which has happened, e.g., the 2011 DigiNotar breach) can be contained by revoking that specific intermediate rather than the root.
Certificate lifecycle:
- Issuance — the applicant generates a key pair and a CSR (Certificate Signing Request), the CA validates domain/organization control (DV/OV/EV validation levels), then signs the certificate.
- Renewal — before expiry, a new certificate is issued; automation (ACME protocol, cert-manager in Kubernetes) has made short-lived certs practical by handling renewal without manual intervention.
- Revocation — if a private key is compromised or a certificate was mis-issued, it must be invalidated before its natural expiry:
- CRL (Certificate Revocation List) — the CA publishes a signed list of revoked certificate serial numbers; clients download and check it. Downsides: lists can grow large, and it’s a “soft-fail” check in most clients (offline CRL is often just ignored).
- OCSP (Online Certificate Status Protocol) — clients query the CA in real time for a single certificate’s status. Faster and lighter than CRL, but introduces a live dependency on the CA (latency, privacy leak, and an outage becomes a fail-open risk) — mitigated by OCSP stapling, where the server itself fetches and caches the signed OCSP response and presents it during the TLS handshake, so clients don’t have to contact the CA at all.
Certificate pinning hardens a specific client against a broader PKI compromise: the client hardcodes (pins) the expected certificate or public key (or its hash) for a given service, and refuses to connect if the presented certificate doesn’t match — even if it’s otherwise validly signed by a trusted CA. This defends against a compromised or coerced CA issuing a rogue certificate for your domain. The tradeoff is operational fragility: pinning must be updated in lockstep with certificate rotation, or you lock yourself out during a routine renewal (several major outages have been caused by exactly this). Modern practice favors pinning the CA/intermediate or using Expect-CT/Certificate Transparency monitoring over strict leaf-certificate pinning, precisely to reduce that fragility.
Enterprise PKI design and failover:
- Multiple CAs / multi-tier hierarchies — large organizations often run their own internal root + issuing CA hierarchy (for internal service certs, VPN, device auth) separate from public CAs used for internet-facing services, so an internal compromise doesn’t affect public trust and vice versa.
- High availability — issuing CAs (and OCSP responders) are deployed redundantly across regions/zones; if a CA is unavailable, automated renewal (cert-manager, ACME clients) must degrade gracefully rather than leaving services running on expired certs.
- Short-lived certificates + automation — the modern trend (SPIFFE/SPIRE, service mesh mTLS, Let’s Encrypt’s 90-day/6-day certs) is to shrink certificate lifetimes dramatically and rely on automated issuance/rotation rather than manual processes and revocation infrastructure, since a cert that expires in hours or days limits the value of stealing its key.
- Disaster recovery — root CA private keys are typically kept in HSMs, offline, with documented, tested procedures for emergency intermediate re-issuance if an intermediate is compromised.
Key Concepts
Key management
Managing cryptographic keys correctly is often harder than choosing the right algorithm — and where most real-world cryptographic failures actually occur (hardcoded keys, keys committed to source control, keys never rotated, one key used for everything).
- KMS (Key Management Service) — a managed or self-hosted service (AWS KMS, GCP Cloud KMS/Cloud HSM, Azure Key Vault, HashiCorp Vault) that generates, stores, rotates, and controls access to cryptographic keys, typically backed by an HSM. Applications call the KMS API to encrypt/decrypt or to request data keys — they never see or handle the raw master key directly.
- HSM (Hardware Security Module) — a dedicated, tamper-resistant hardware device that generates and stores keys such that the private key material can never be exported in plaintext, even by administrators; all cryptographic operations happen inside the device. This is the physical root of trust behind most enterprise KMS offerings and CA root keys.
- Envelope encryption — the standard pattern for encrypting large amounts of data with KMS-backed keys without sending the data itself to the KMS: a KMS-managed master key (Key Encryption Key, KEK) encrypts a randomly generated data key (Data Encryption Key, DEK); the DEK (not the KEK) encrypts the actual data locally; the encrypted DEK is stored alongside the encrypted data. To decrypt, the application sends the encrypted DEK to the KMS, gets back the plaintext DEK, and decrypts the data locally. This means the master key never leaves the KMS/HSM boundary and bulk data never has to be sent over the network to be encrypted/decrypted.
- 01KMS / HSMMaster Key (KEK) lives here, never leaves
- encrypts/decrypts02Data Encryption Key (DEK)random, per-object/per-file
- encrypts/decrypts (locally, fast, symmetric)03Actual datalarge payload
- Key rotation — periodically replacing keys (KEKs on a schedule measured in months/years; DEKs frequently, sometimes per-object) to limit the blast radius of an undetected compromise and to satisfy compliance requirements (PCI-DSS mandates periodic key rotation). Rotation must support decrypting data encrypted under old key versions while encrypting new data under the current version — most KMS products version keys transparently for this reason.
- Secrets vs. keys — a subtle but important distinction: a key is cryptographic material used within a crypto operation (encrypt/decrypt/sign/verify); a secret is any sensitive value an application needs (API tokens, database passwords, keys themselves). Secrets managers (Vault, AWS Secrets Manager) handle the broader secret lifecycle — dynamic generation, leasing, and revocation of credentials — while a KMS specifically manages cryptographic keys and operations. In practice the two are often layered: a secrets manager might itself be unlocked/encrypted using a key from a KMS.
Comparison: symmetric vs. asymmetric vs. hashing
| Symmetric encryption | Asymmetric encryption | Hashing | |
|---|---|---|---|
| Purpose | Confidentiality | Confidentiality, key exchange, digital signatures | Integrity, authenticity (when combined with signing), password verification |
| Keys | One shared secret key | Public/private key pair | No key (or a key for HMAC) |
| Reversible? | Yes (with the key) | Yes (with the private key) | No — one-way by design |
| Speed | Fast | Slow (100–1000x slower than symmetric) | Fast (except deliberately slow password hashes) |
| Typical algorithms | AES-256-GCM, ChaCha20-Poly1305 | RSA-2048/4096, ECC (P-256, X25519) | SHA-256, SHA-3, BLAKE2; bcrypt/Argon2 for passwords |
| Typical use case | Encrypting bulk data, disk/DB encryption, TLS session data | TLS handshake key exchange, certificates, code/commit signing | Checksums, Git object IDs, digital signature digests, password storage |
Best Practices
- Never roll your own crypto. Do not design new algorithms or reimplement primitives from a paper; use well-reviewed, standard libraries (OpenSSL/BoringSSL, libsodium, platform crypto APIs) with high-level, misuse-resistant APIs where possible.
- Use vetted, high-level libraries over low-level primitives. Prefer libsodium/NaCl-style APIs (
crypto_secretbox,crypto_box) or your language’s audited crypto library over hand-assembling AES + HMAC yourself — subtle mistakes (e.g., not verifying the MAC before decrypting, timing side channels in comparison) are exactly how supposedly-correct implementations get broken. - Always use AEAD ciphers for encryption (AES-GCM, ChaCha20-Poly1305) instead of unauthenticated modes (CBC, CTR) that require you to bolt on your own MAC correctly.
- Never use a fast general-purpose hash for passwords. Use Argon2id (preferred), bcrypt, or scrypt, with an appropriately tuned work factor, and let the library handle salting.
- Use cryptographically secure randomness only.
/dev/urandom,openssl rand, or your language’s CSPRNG (e.g., Python’ssecrets, notrandom; Node’scrypto.randomBytes, notMath.random()) — weak or predictable randomness has broken real systems (e.g., the 2008 Debian OpenSSL PRNG bug, weak IoT device key generation). - Never hardcode keys or secrets in source code, config files, or container images. Load them at runtime from a KMS/secrets manager; scan repos for accidentally committed keys (gitleaks, trufflehog) as a CI gate.
- Enforce forward secrecy — require ECDHE key exchange in TLS configuration and disable static RSA key exchange and legacy protocol versions (SSLv3, TLS 1.0/1.1).
- Rotate keys on a schedule and after any suspected compromise, and design systems so rotation doesn’t require downtime (version keys, support decrypting under old + new keys during a transition window).
- Prefer short-lived certificates and automated issuance/renewal (ACME, cert-manager, SPIFFE/SPIRE) over long-lived certs managed by hand.
- Pin deliberately, not by default — certificate/public-key pinning is powerful but operationally risky; understand the rollover plan before enabling it, and prefer pinning intermediates/CAs over leaf certs.
- Validate certificates properly in code — check the full chain, hostname (SAN, not just CN), expiry, and revocation status; never disable certificate validation “temporarily” (
verify=False,-k/--insecure) outside of a throwaway local test, and grep CI/CD configs for these flags. - Treat compliance-driven crypto requirements as a floor, not a ceiling — FIPS 140-2/3 validated modules, PCI-DSS key rotation, and similar mandates define minimums; align architecture choices with them from the start rather than retrofitting.
- Log and monitor key usage and certificate expiry — expired certificates causing outages, and unnoticed unauthorized key usage, are both common, avoidable incidents; alert well before expiry (e.g., 30/14/3 days).
References
- NIST SP 800-57: Recommendation for Key Management
- NIST FIPS 197: Advanced Encryption Standard (AES)
- RFC 8446 — The Transport Layer Security (TLS) Protocol Version 1.3
- OWASP Cryptographic Storage Cheat Sheet
- OWASP Password Storage Cheat Sheet
- OWASP Transport Layer Security Cheat Sheet
- NIST SP 800-52 Rev. 2: Guidelines for TLS Implementations
- RFC 6960 — Online Certificate Status Protocol (OCSP)
Related topics: Networking Fundamentals for Security · Identity & Access Management · Secure Coding & Web Application Security