Applied cryptography and PKI standards
Criteria verified as of August 2026. Re-verify on the web before committing to anything (§8).
1. Scope and triggers
Applies when choosing, implementing or reviewing: algorithms and modes (AEAD, encryption at rest,
signing), key derivation and password hashing, randomness generation, nonce/IV
management, digital signatures and JOSE/COSE formats, TLS configuration and its verification,
certificate lifecycle and ACME automation (Let's Encrypt, step-ca, cert-manager,
DNS-01 challenge), internal PKI design and CA hierarchy, mTLS and pinning, key management
with HSM/KMS (envelope encryption, wrapping, rotation, custody), code and artifact
signing, backup encryption, and post-quantum inventory and migration.
Not applicable: see post-quantum-crypto-standards (critical boundary: the PKI, the
certificate lifecycle and classical crypto are decided here; the whole post-quantum transition
is theirs — the status of FIPS 203/204/205/206 and HQC, the NIST IR 8547 and CNSA 2.0 timelines,
hybrids in TLS/SSH/IPsec and the migration order by data type. If the question carries a migration
date or the name of a PQC algorithm, the other one governs), networking-standards (TLS termination
at the edge, proxies, WireGuard, DNSSEC), kubernetes-standards (deploying cert-manager and
signature verification in admission), cicd-standards (artifact signing inside the pipeline and the
runner's OIDC), identity-access-management-standards (tokens, sessions and authentication policy),
appsec-standards (insecure crypto use found in code review),
secrets-management-standards (storage and distribution of already-generated
secrets), assembly-standards (critical boundary: the choice of algorithm,
curve, mode, key size and the whole key lifecycle is decided here; there, only the
constant-time implementation —no branches or memory accesses dependent on the secret— and
the erasure of secrets the compiler cannot optimise away. The rule both repeat and which admits
no exception: FORBIDDEN to implement your own cryptography; an audited library is used, and
if someone is writing cryptographic assembly, the prior question is why),
solidity-standards (the use of the primitives the chain already exposes —signature
verification, EIP-712, ecrecover and its malleability— is theirs; the choice and custody of the
keys, here), govtech-eidas-standards (the eIDAS regime is theirs: advanced versus qualified
electronic signature, qualified trust service provider and trusted lists, qualified time stamp,
AdES formats and their long-term preservation, and what evidential value each one has. Here the
cryptography underneath —algorithm, curve, HSM custody, chain and revocation—; the
rule that avoids the expensive mistake: a technically valid signature is not a qualified
signature, and that is decided by their framework, not by the algorithm).
2. Default decisions
Verify the latest version on the web before committing to it in a real project (§8). The
PQC migration dates and the maximum certificate lifetime changed in 2025-2026: do not
state them from memory.
| Need |
Default |
Justifiable alternative |
Vetoed |
| Authenticated symmetric encryption |
AES-256-GCM (managed nonce) or ChaCha20-Poly1305 (no AES-NI) |
AES-GCM-SIV (RFC 8452) or AES-SIV (RFC 5297) if the nonce cannot be guaranteed unique; XChaCha20-Poly1305 with a random nonce |
ECB, CBC/CTR without a MAC, DES/3DES, RC4, Blowfish |
| Encryption with a low-entropy key (password/PSK) |
An AEAD with key commitment or a construction that binds the key to the ciphertext |
A strong KDF + a standard AEAD, documenting the risk |
Plain AES-GCM/ChaCha20-Poly1305 (they are not key-committing) |
| Password hashing |
Argon2id |
scrypt; bcrypt in legacy; PBKDF2-HMAC-SHA-256 if FIPS is required |
MD5, SHA-1, "salted" SHA-256, home-made hashing |
| General-purpose hash |
SHA-256/SHA-512 or SHA-3/BLAKE2-3 |
— |
MD5, SHA-1 (not even in "checksums", they end up being used as security) |
| Digital signature |
Ed25519 (RFC 8032) |
ECDSA P-256 (with RFC 6979) if NIST/FIPS is required; RSA-PSS ≥3072 for legacy interoperability |
RSA PKCS#1 v1.5 in new designs, RSA <3072, DSA |
| Transport |
TLS 1.3; TLS 1.2 only with AEAD+PFS suites |
mTLS with your own PKI for east-west |
TLS 1.0/1.1 (RFC 8996), insecure renegotiation, suites without PFS |
| Public certificates |
Automated ACME (Let's Encrypt or another ACME CA) |
A commercial CA when a third party requires it |
Manual issuance, self-signed on public surfaces |
| Internal PKI |
step-ca or the provider's managed CA; cert-manager in Kubernetes |
Your own offline CA with an HSM for the root |
Reusing the internal CA for public TLS; a CA with no revocation plan |
| Key custody |
KMS/HSM (FIPS 140-3) with envelope encryption |
A file encrypted with a key in the KMS, if there is no HSM |
Keys in repos, images, environment variables in the clear or in the same backup as the data |
| Artifact signing |
Sigstore/cosign keyless (the CI's OIDC, a transparency log) |
minisign/age + SSH signing in small environments; GPG only for an external requirement |
Unsigned artifacts on the path to production |
| File/backup encryption |
age (or the native encryption of restic/kopia/borg) |
GPG only for inherited interoperability |
"Password-protected" ZIP, home-made encryption |
3. Structure and conventions
AEAD, nonces and real limits
- Never reuse a nonce with the same key: in AES-GCM and ChaCha20-Poly1305, repetition
does not degrade, it breaks things (recovery of the authenticator and of the plaintext).
- AES-GCM uses a 96-bit nonce: with random nonces, the practical limit is of the order
of 2³² messages per key (a birthday bound; SP 800-38D and FIPS 140-3 IG C.H
additionally restrict how the nonce is generated). With a deterministic counter partitioned per
sender, the ceiling is much higher — but it requires reliable state.
- If you cannot guarantee uniqueness: AES-GCM-SIV / AES-SIV (nonce-misuse resistant)
or nonce extension (XChaCha20-Poly1305; constructions such as XAES-256-GCM or
DNDK-GCM, still in CFRG draft — verify their status before depending on them).
- Key commitment: the standard AEADs are not key-committing. When the key derives
from a password or a low-entropy PSK, or when the receiver tries several keys,
partitioning oracles appear (USENIX Security '21) that allow recovering the key. Use an AEAD
with commitment or explicitly bind the key (a hash of the key in the AAD).
- The AAD is not optional: put the context in it (tenant, schema version, object id)
so a ciphertext is not reusable in another context.
Password hashing (parameters, not "use bcrypt")
OWASP minimums (August 2026) — they rise with hardware, re-verify (§8):
| Algorithm |
Minimum parameters |
Note |
| Argon2id |
m=19 MiB, t=2, p=1 (or equivalents: m=12 MiB, t=3…) |
Tune upwards to ~250-500 ms of verification; RFC 9106 recommends considerably larger configurations |
| scrypt |
N=2^17, r=8, p=1 |
The second option if there is no Argon2id |
| bcrypt |
cost ≥ 10, a 72-byte limit |
Pre-hash with SHA-256 (+base64) if you accept long passwords |
| PBKDF2 |
≥ 600,000 iterations with HMAC-SHA-256 |
Only for a FIPS requirement |
- A unique salt per password (the library generates it). A pepper optionally in the KMS/HSM, as
defence in depth, never as a substitute.
- Transparent rehashing when parameters are raised: it is detected at login and updated.
- Constant-time comparison in everything that compares secrets (tokens, HMACs, hashes).
Randomness
- The system source always:
getrandom(2)/getentropy, /dev/urandom,
BCryptGenRandom, or the language's cryptographic wrapper (secrets in Python,
crypto/rand in Go, crypto.randomBytes/getRandomValues, SecureRandom).
- FORBIDDEN for any value with a security function:
Math.random(), rand(),
java.util.Random, Python's random module, PRNGs seeded with the time or the PID.
- Careful with cloned VMs, containers and golden images: entropy and PRNG state get
duplicated; guarantee a reseed at boot.
Signatures and JOSE
- Ed25519 by default; ECDSA P-256 if the ecosystem requires it (with a deterministic signature or a
correct RNG: a repeated
k nonce reveals the private key); RSA-PSS rather than PKCS#1 v1.5.
- JOSE/JWT (RFC 8725):
alg against the verifier's allowlist, never the token's;
none forbidden; accepting HMAC where you expect asymmetric is forbidden (algorithm
confusion); kid validated against the known JWKS; explicit typ.
- Commit/tag signing: SSH signing (
gpg.format = ssh) with a versioned allowed_signers,
or GPG if the process already requires it. Verification is done in CI, not "by eye".
PKI: hierarchy and lifecycle
- An offline root (an HSM or split material), intermediates by purpose (server TLS,
client mTLS, code signing) and short-lived leaves. A CA that issues everything is a
single point of compromise.
- Restrict: minimal
keyUsage/extendedKeyUsage, nameConstraints on the internal
intermediates, a correct SAN (the CN is decorative), no wildcards shared between services.
- Automation or there is no PKI: ACME (step-ca, cert-manager,
certbot/lego) with
unattended renewal and a margin ≥ 1/3 of the certificate's lifetime. DNS-01 for wildcards and
internal hosts, with least-privilege DNS credentials (delegate only
_acme-challenge to a zone of your own).
- The maximum lifetime of public TLS certificates is being reduced in phases (the CA/Browser
Forum's ballot SC-081, with milestones down to 47 days and a parallel reduction in domain
validation reuse). Verify the current timeline and figures (§8); the
design consequence does not change: 100% automatic renewal with no human in the path.
- Revocation: CRL/OCSP have irregular delivery and adoption → the real defence is a short
lifetime + fast reissuance. The mandatory operational question: if your CA revokes within 24 h
(a Baseline Requirements obligation in incidents), can you reissue and deploy across the whole
fleet in 24 h? If not, you have a latent incident.
- Monitor Certificate Transparency for your domains: it detects mis-issuance without the
risks of pinning.
mTLS and pinning
- Identity in the SAN (a SPIFFE or DNS URI), full chain validation against your CA
(not against the system trust store) and automatic rotation of the leaves.
- HPKP is dead (removed from the browsers). If you pin in a native app: pin public
keys, with a pinset and backup pins, only your own endpoints, with a remote kill
switch and rotation monitoring. A pin with no rollback plan is a scheduled brick: the app
store's review cycle is slower than any emergency rotation.
- Never pin third-party endpoints you do not control.
Key management
- Envelope encryption: a DEK per object/tenant, wrapped by a KEK that lives in the KMS/HSM.
Wrapping with AES-KW (RFC 3394) or an AEAD; never "encrypt the key with the same key".
- An explicit crypto-period per key and tested rotation: a key version identifier
alongside the ciphertext so the KEK can be rotated without re-encrypting the whole corpus.
- Separation of duties: whoever administers the KMS does not decrypt data; every operation with a
root key is audited and under dual control.
- Root custody: Shamir/quorum or split physical custody, with a rehearsed recovery
procedure.
- Backups: encryption with a key that does not live in the backed-up system, immutable
copies (Object Lock / an append-only repository) and a tested restore.
age (v1.1.x already
incorporates hybrid post-quantum recipients mlkem768x25519 and age-inspect) or the native
encryption of restic (0.18.x, zstd by default since 0.14), kopia or borg.
Post-quantum — ceded to post-quantum-crypto-standards
The whole transition lives there: the real status of FIPS 203/204/205/206 and HQC, the timelines of
NIST IR 8547 and CNSA 2.0 with their provenance, hybrids in TLS/SSH/IPsec with code point and
support by version, key and signature sizes, and the migration order by data type.
Do not duplicate any of those dates here: they expire and they diverge.
What does remain this skill's business, because it is applied crypto and not transition:
- Cryptographic agility as a design requirement: algorithm and key version as
metadata of the encrypted data, an isolated crypto layer behind an interface, and a CBOM
(CycloneDX 1.6 = ECMA-424 introduced cryptographic assets; 1.7 refines them) generated in
CI to know which algorithms you actually use. Without an inventory there is no migration — and the
inventory is built with this skill's tools and exploited with the other one's.
- Backup encryption with a key that does not live in the backed-up system:
age (v1.1.x already
incorporates hybrid mlkem768x25519 recipients) or the native encryption of restic/kopia/borg.
4. Quality and testing (CI gates)
- Crypto linters:
gosec/bandit/semgrep/language analyser rules
for MD5/SHA-1/DES/ECB, InsecureSkipVerify/verify=False, hardcoded keys and non-cryptographic
PRNGs. They break the build.
- Secret/key scanning (the specific scanner and its licence are set by
secrets-management-standards; verify before committing to it): a private key or CA material in
the repo = a broken build and immediate rotation, not a TODO.
- Known-answer tests (KAT) for any code that touches crypto of its own, plus negative
tests: a corrupted tag, a detected repeated nonce, an expired certificate, an incomplete
chain, a hostname that does not match, a tampered
alg.
- TLS scanning (
testssl.sh or sslyze) against staging on every release and against
production on a schedule: versions, suites, chain, OCSP stapling, HSTS.
- Expiry monitoring as an operational test: an alert with a margin ≥ 3× the renewal
cycle, and fail the pipeline if a managed certificate was not renewed in time.
- Signature verification at deployment: an artifact without a valid signature is not installed
(the pipeline detail is in
cicd-standards, admission in kubernetes-standards).
5. Security
- Forbidden to implement your own primitives. Use the maintained cryptographic library of
your platform (libsodium, the language's stdlib, OpenSSL/AWS-LC via a high-level
wrapper). "Rolling your own crypto" includes composing an AEAD by hand, inventing padding or
chaining hashes.
- Side channels: constant-time comparison, care with the cache and with distinguishable
error messages (padding/MAC oracles). Decryption errors are one single generic
error.
- Do not leak into logs keys, IVs/nonces alongside the ciphertext without control, nor fragments of
sensitive material; exception dumps are an exfiltration channel.
- Private key files:
0600 permissions, a dedicated owner, outside the container image
and outside the backup of the system they protect.
- Strict validation of the certificate/hostname pair in every client (SDKs included);
disabling verification "temporarily" is a finding, even in development.
- Cryptographic dependencies: follow the CVEs of the TLS/crypto library in use and its support
cycle (LTS vs non-LTS) — it is the component with the least tolerance for unpatched versions.
- Compliance: FIPS 140-3 replaces 140-2; the 140-2 certificates move to Historical
on 21-Sep-2026 (the systems keep working, but they stop counting for new
federal acquisitions). If there is a requirement, verify the specific module in the CMVP, not the
vendor's marketing claim.
6. Operability
- Renewal is a service, not a task: unattended ACME, process reload with no
downtime (
nginx -s reload, hot reload of the binary), and a periodic test that the reload
really picks up the new certificate.
- The CA's rate limits (Let's Encrypt and equivalents) accounted for in the design: staging
for tests, do not issue for every ephemeral deployment.
- Performance: TLS 1.3 with session resumption (careful with
0-RTT: only for idempotent
requests), OCSP stapling, and hardware acceleration where it exists. Software encryption
is rarely the bottleneck; the handshake is.
- HSM/KMS: latency and the operations-per-second limit are plannable capacity (and
cost). Cache unwrapped DEKs in memory with a TTL, never persist them in the clear.
- Observability: certificate expiry metrics, handshake failures by cause,
negotiated version/suite, KMS errors and the renewal rate. Alert on symptoms
(failed handshakes rising), not only on expiry.
- The clock: certificate validation depends on time. Reliable, monitored NTP; a clock
drift presents itself as "TLS broken for no reason".
7. Sustainability and prohibitions
- Cadence: review password hashing parameters and TLS configuration at least
annually (they rise with hardware) and the PQC plan every six months while the
transition lasts. The reduction of certificate lifetimes forces a review of the automation each
time a phase changes.
- Every exception (inherited RSA-2048, TLS 1.2 for an old client, GPG for a third party)
carries an exit date and a ticket.
- Keep the CBOM alive, not as an annual export: it is the migration's work list.
FORBIDDEN
- ❌ MD5 and SHA-1 with a security function; DES/3DES, RC4, ECB mode.
- ❌ Encryption without authentication (bare CBC/CTR) and improvised MAC-then-encrypt.
- ❌ Reusing a nonce/IV with the same key; a predictable IV or a global counter with no partitioning.
- ❌ Passwords with a fast hash (salted SHA-256/512), home-made schemes or hand-rolled rounds.
- ❌ A non-cryptographic PRNG for keys, tokens, salts, nonces or identifiers.
- ❌ Private keys or CA material in repos, images, artifacts or logs.
- ❌ RSA <3072 in new keys; ECDSA with a dubious RNG; PKCS#1 v1.5 for signing in new designs.
- ❌ TLS 1.0/1.1, suites without PFS,
InsecureSkipVerify/verify=False/--no-check-certificate.
- ❌ HPKP; pinning without backup pins, without a kill switch or over third-party endpoints.
- ❌ Certificates issued or renewed by hand in production; a wildcard shared between unrelated services.
- ❌ An online root CA, with no name constraints and no revocation plan; an internal CA used for public surfaces.
- ❌ Backups whose key lives in the backed-up system, or with no tested restore.
- ❌ Implementing your own cryptographic primitives.
Quick review checklist
8. Mandatory web verification
Before committing to an algorithm, version, date or parameter in a deliverable:
- NIST's PQC status: FIPS 203/204/205 (and FIPS 206 / HQC), and the transition
timeline of NIST IR 8547 (RSA/ECC deprecation) and of CNSA 2.0 by category.
- Maximum lifetime of public TLS certificates: the current phase of the CA/Browser Forum's
ballot SC-081 and the domain validation reuse periods.
- Hashing parameters in the OWASP Password Storage Cheat Sheet (they change with
hardware) and in the current revision of NIST SP 800-63B.
- Versions and EOL of OpenSSL (or AWS-LC/BoringSSL), step-ca, cert-manager,
age,
restic/kopia/borg, cosign and testssl.sh, plus their open CVEs.
- Real support for PQC hybrids in TLS (the exact group name, browsers, server)
and in your KMS/HSM by region, before promising "quantum-safe".
- Your CA's news: ACME profiles, ultra-short-lived certificates, changes in
OCSP/CRL and rate limits.
- FIPS 140-3 validation of the specific module in the CMVP if there is a compliance requirement.
If the web contradicts this document, the web wins — flag the discrepancy.
1---2name: cryptography-pki-standards3description: Applied cryptography and PKI standards. Use when choosing algorithms or modes (AES-GCM, ChaCha20-Poly1305, Ed25519, RSA-PSS), Argon2id password hashing, TLS 1.3 config, testssl.sh, ACME/Let's Encrypt, step-ca, cert-manager, mTLS, HSM/KMS key rotation, cosign/GPG signing, crypto agility and CBOM inventory.4---56# Applied cryptography and PKI standards78Criteria verified as of **August 2026**. Re-verify on the web before committing to anything (§8).910## 1. Scope and triggers1112Applies when choosing, implementing or reviewing: algorithms and modes (AEAD, encryption at rest,13signing), key derivation and password hashing, randomness generation, nonce/IV14management, digital signatures and JOSE/COSE formats, TLS configuration and its verification,15certificate lifecycle and ACME automation (Let's Encrypt, step-ca, cert-manager,16DNS-01 challenge), internal PKI design and CA hierarchy, mTLS and pinning, key management17with HSM/KMS (envelope encryption, wrapping, rotation, custody), code and artifact18signing, backup encryption, and post-quantum inventory and migration.1920**Not applicable**: see `post-quantum-crypto-standards` (**critical boundary**: the PKI, the21certificate lifecycle and classical crypto are decided **here**; **the whole post-quantum transition22is theirs** — the status of FIPS 203/204/205/206 and HQC, the NIST IR 8547 and CNSA 2.0 timelines,23hybrids in TLS/SSH/IPsec and the migration order by data type. If the question carries a migration24date or the name of a PQC algorithm, the other one governs), `networking-standards` (TLS termination25at the edge, proxies, WireGuard, DNSSEC), `kubernetes-standards` (deploying cert-manager and26signature verification in admission), `cicd-standards` (artifact signing inside the pipeline and the27runner's OIDC), `identity-access-management-standards` (tokens, sessions and authentication policy),28`appsec-standards` (insecure crypto use found in code review),29`secrets-management-standards` (storage and distribution of already-generated30secrets), `assembly-standards` (**critical boundary**: the choice of algorithm,31curve, mode, key size and the whole key lifecycle is decided **here**; there, only the32constant-time **implementation** —no branches or memory accesses dependent on the secret— and33the erasure of secrets the compiler cannot optimise away. The rule both repeat and which admits34no exception: **FORBIDDEN to implement your own cryptography**; an audited library is used, and35if someone is writing cryptographic assembly, the prior question is why),36`solidity-standards` (the use of the primitives the chain already exposes —signature37verification, EIP-712, `ecrecover` and its malleability— is theirs; the choice and custody of the38keys, here), `govtech-eidas-standards` (**the eIDAS regime is theirs**: advanced versus qualified39electronic signature, qualified trust service provider and trusted lists, qualified time stamp,40AdES formats and their long-term preservation, and what evidential value each one has. **Here the41cryptography underneath** —algorithm, curve, HSM custody, chain and revocation—; the42rule that avoids the expensive mistake: **a technically valid signature is not a qualified43signature**, and that is decided by their framework, not by the algorithm).4445## 2. Default decisions4647> Verify the latest version on the web before committing to it in a real project (§8). The48> PQC migration dates and the maximum certificate lifetime changed in 2025-2026: do not49> state them from memory.5051| Need | Default | Justifiable alternative | Vetoed |52|---|---|---|---|53| Authenticated symmetric encryption | **AES-256-GCM** (managed nonce) or **ChaCha20-Poly1305** (no AES-NI) | **AES-GCM-SIV** (RFC 8452) or **AES-SIV** (RFC 5297) if the nonce cannot be guaranteed unique; XChaCha20-Poly1305 with a random nonce | ECB, CBC/CTR without a MAC, DES/3DES, RC4, Blowfish |54| Encryption with a low-entropy key (password/PSK) | An AEAD **with key commitment** or a construction that binds the key to the ciphertext | A strong KDF + a standard AEAD, documenting the risk | Plain AES-GCM/ChaCha20-Poly1305 (they are not key-committing) |55| Password hashing | **Argon2id** | scrypt; bcrypt in legacy; **PBKDF2-HMAC-SHA-256** if FIPS is required | MD5, SHA-1, "salted" SHA-256, home-made hashing |56| General-purpose hash | **SHA-256/SHA-512** or SHA-3/BLAKE2-3 | — | MD5, SHA-1 (not even in "checksums", they end up being used as security) |57| Digital signature | **Ed25519** (RFC 8032) | ECDSA P-256 (with RFC 6979) if NIST/FIPS is required; **RSA-PSS** ≥3072 for legacy interoperability | RSA PKCS#1 v1.5 in new designs, RSA <3072, DSA |58| Transport | **TLS 1.3**; TLS 1.2 only with AEAD+PFS suites | mTLS with your own PKI for east-west | TLS 1.0/1.1 (RFC 8996), insecure renegotiation, suites without PFS |59| Public certificates | **Automated ACME** (Let's Encrypt or another ACME CA) | A commercial CA when a third party requires it | Manual issuance, self-signed on public surfaces |60| Internal PKI | **step-ca** or the provider's managed CA; **cert-manager** in Kubernetes | Your own offline CA with an HSM for the root | Reusing the internal CA for public TLS; a CA with no revocation plan |61| Key custody | **KMS/HSM** (FIPS 140-3) with envelope encryption | A file encrypted with a key in the KMS, if there is no HSM | Keys in repos, images, environment variables in the clear or in the same backup as the data |62| Artifact signing | **Sigstore/cosign keyless** (the CI's OIDC, a transparency log) | minisign/`age` + SSH signing in small environments; GPG only for an external requirement | Unsigned artifacts on the path to production |63| File/backup encryption | **age** (or the native encryption of restic/kopia/borg) | GPG only for inherited interoperability | "Password-protected" ZIP, home-made encryption |6465## 3. Structure and conventions6667### AEAD, nonces and real limits6869- **Never reuse a nonce with the same key**: in AES-GCM and ChaCha20-Poly1305, repetition70 does not degrade, it **breaks** things (recovery of the authenticator and of the plaintext).71- AES-GCM uses a 96-bit nonce: with **random** nonces, the practical limit is of the order72 of **2³² messages per key** (a birthday bound; SP 800-38D and FIPS 140-3 IG C.H73 additionally restrict how the nonce is generated). With a deterministic counter partitioned per74 sender, the ceiling is much higher — but it requires reliable state.75- If you cannot guarantee uniqueness: **AES-GCM-SIV / AES-SIV** (nonce-misuse resistant)76 or nonce extension (XChaCha20-Poly1305; constructions such as XAES-256-GCM or77 DNDK-GCM, still in CFRG draft — verify their status before depending on them).78- **Key commitment**: the standard AEADs are not key-committing. When the key derives79 from a password or a low-entropy PSK, or when the receiver tries several keys,80 *partitioning oracles* appear (USENIX Security '21) that allow recovering the key. Use an AEAD81 with commitment or explicitly bind the key (a hash of the key in the AAD).82- The AAD is not optional: put the context in it (tenant, schema version, object id)83 so a ciphertext is not reusable in another context.8485### Password hashing (parameters, not "use bcrypt")8687OWASP minimums (August 2026) — **they rise with hardware, re-verify (§8)**:8889| Algorithm | Minimum parameters | Note |90|---|---|---|91| Argon2id | `m=19 MiB, t=2, p=1` (or equivalents: `m=12 MiB, t=3`…) | Tune **upwards** to ~250-500 ms of verification; RFC 9106 recommends considerably larger configurations |92| scrypt | `N=2^17, r=8, p=1` | The second option if there is no Argon2id |93| bcrypt | cost ≥ **10**, a **72-byte** limit | Pre-hash with SHA-256 (+base64) if you accept long passwords |94| PBKDF2 | ≥ **600,000** iterations with HMAC-SHA-256 | Only for a FIPS requirement |9596- A unique salt per password (the library generates it). A **pepper** optionally in the KMS/HSM, as97 defence in depth, never as a substitute.98- Transparent rehashing when parameters are raised: it is detected at login and updated.99- Constant-time comparison in everything that compares secrets (tokens, HMACs, hashes).100101### Randomness102103- The system source **always**: `getrandom(2)`/`getentropy`, `/dev/urandom`,104 `BCryptGenRandom`, or the language's cryptographic wrapper (`secrets` in Python,105 `crypto/rand` in Go, `crypto.randomBytes`/`getRandomValues`, `SecureRandom`).106- **FORBIDDEN** for any value with a security function: `Math.random()`, `rand()`,107 `java.util.Random`, Python's `random` module, PRNGs seeded with the time or the PID.108- Careful with cloned VMs, containers and golden images: entropy and PRNG state get109 duplicated; guarantee a reseed at boot.110111### Signatures and JOSE112113- Ed25519 by default; ECDSA P-256 if the ecosystem requires it (with a deterministic signature or a114 correct RNG: a repeated `k` nonce reveals the private key); RSA-PSS rather than PKCS#1 v1.5.115- JOSE/JWT (RFC 8725): `alg` against the **verifier's allowlist**, never the token's;116 `none` forbidden; accepting HMAC where you expect asymmetric is forbidden (algorithm117 confusion); `kid` validated against the known JWKS; explicit `typ`.118- Commit/tag signing: SSH signing (`gpg.format = ssh`) with a versioned `allowed_signers`,119 or GPG if the process already requires it. Verification is done in CI, not "by eye".120121### PKI: hierarchy and lifecycle122123- **An offline root** (an HSM or split material), intermediates **by purpose** (server TLS,124 client mTLS, code signing) and **short-lived** leaves. A CA that issues everything is a125 single point of compromise.126- Restrict: minimal `keyUsage`/`extendedKeyUsage`, `nameConstraints` on the internal127 intermediates, a correct SAN (the CN is decorative), no wildcards shared between services.128- **Automation or there is no PKI**: ACME (step-ca, cert-manager, `certbot`/`lego`) with129 unattended renewal and a margin ≥ 1/3 of the certificate's lifetime. DNS-01 for wildcards and130 internal hosts, with **least-privilege** DNS credentials (delegate only131 `_acme-challenge` to a zone of your own).132- The maximum lifetime of public TLS certificates is being **reduced in phases** (the CA/Browser133 Forum's ballot SC-081, with milestones down to 47 days and a parallel reduction in domain134 validation reuse). **Verify the current timeline and figures (§8)**; the135 design consequence does not change: 100% automatic renewal with no human in the path.136- Revocation: CRL/OCSP have irregular delivery and adoption → the real defence is a **short137 lifetime + fast reissuance**. The mandatory operational question: if your CA revokes within 24 h138 (a Baseline Requirements obligation in incidents), can you reissue and deploy across the whole139 fleet in 24 h? If not, you have a latent incident.140- Monitor **Certificate Transparency** for your domains: it detects mis-issuance without the141 risks of pinning.142143### mTLS and pinning144145- Identity in the SAN (a SPIFFE or DNS URI), **full** chain validation against your CA146 (not against the system trust store) and automatic rotation of the leaves.147- **HPKP is dead** (removed from the browsers). If you pin in a native app: pin **public148 keys**, with a **pinset and backup pins**, only your own endpoints, with a **remote kill149 switch** and rotation monitoring. A pin with no rollback plan is a scheduled brick: the app150 store's review cycle is slower than any emergency rotation.151- Never pin third-party endpoints you do not control.152153### Key management154155- **Envelope encryption**: a DEK per object/tenant, wrapped by a KEK that lives in the KMS/HSM.156 Wrapping with AES-KW (RFC 3394) or an AEAD; never "encrypt the key with the same key".157- An explicit crypto-period per key and **tested rotation**: a key version identifier158 alongside the ciphertext so the KEK can be rotated without re-encrypting the whole corpus.159- Separation of duties: whoever administers the KMS does not decrypt data; every operation with a160 root key is audited and under dual control.161- Root custody: Shamir/quorum or split physical custody, with a **rehearsed** recovery162 procedure.163- Backups: encryption with a key that does **not** live in the backed-up system, immutable164 copies (Object Lock / an append-only repository) and a tested restore. `age` (v1.1.x already165 incorporates hybrid post-quantum recipients `mlkem768x25519` and `age-inspect`) or the native166 encryption of restic (0.18.x, zstd by default since 0.14), kopia or borg.167168### Post-quantum — **ceded to `post-quantum-crypto-standards`**169170The whole transition lives there: the real status of FIPS 203/204/205/206 and HQC, the timelines of171NIST IR 8547 and CNSA 2.0 with their provenance, hybrids in TLS/SSH/IPsec with code point and172support by version, key and signature sizes, and the migration order by data type.173**Do not duplicate any of those dates here**: they expire and they diverge.174175What does remain this skill's business, because it is applied crypto and not transition:176177- **Cryptographic agility** as a design requirement: algorithm and key version as178 metadata of the encrypted data, an isolated crypto layer behind an interface, and a **CBOM**179 (CycloneDX 1.6 = ECMA-424 introduced cryptographic assets; 1.7 refines them) generated in180 CI to know which algorithms you actually use. Without an inventory there is no migration — and the181 inventory is built with this skill's tools and exploited with the other one's.182- Backup encryption with a key that does not live in the backed-up system: `age` (v1.1.x already183 incorporates hybrid `mlkem768x25519` recipients) or the native encryption of restic/kopia/borg.184185## 4. Quality and testing (CI gates)1861871. **Crypto linters**: `gosec`/`bandit`/`semgrep`/language analyser rules188 for MD5/SHA-1/DES/ECB, `InsecureSkipVerify`/`verify=False`, hardcoded keys and non-cryptographic189 PRNGs. They break the build.1902. **Secret/key scanning** (the specific scanner and its licence are set by191 `secrets-management-standards`; verify before committing to it): a private key or CA material in192 the repo = a broken build and immediate rotation, not a TODO.1933. **Known-answer tests (KAT)** for any code that touches crypto of its own, plus negative194 tests: a corrupted tag, a detected repeated nonce, an expired certificate, an incomplete195 chain, a hostname that does not match, a tampered `alg`.1964. **TLS scanning** (`testssl.sh` or `sslyze`) against staging on every release and against197 production on a schedule: versions, suites, chain, OCSP stapling, HSTS.1985. **Expiry monitoring** as an operational test: an alert with a margin ≥ 3× the renewal199 cycle, and fail the pipeline if a managed certificate was not renewed in time.2006. **Signature verification** at deployment: an artifact without a valid signature is not installed201 (the pipeline detail is in `cicd-standards`, admission in `kubernetes-standards`).202203## 5. Security204205- **Forbidden to implement your own primitives.** Use the maintained cryptographic library of206 your platform (libsodium, the language's stdlib, OpenSSL/AWS-LC via a high-level207 wrapper). "Rolling your own crypto" includes composing an AEAD by hand, inventing padding or208 chaining hashes.209- Side channels: constant-time comparison, care with the cache and with distinguishable210 error messages (padding/MAC oracles). Decryption errors are **one single** generic211 error.212- Do not leak into logs keys, IVs/nonces alongside the ciphertext without control, nor fragments of213 sensitive material; exception dumps are an exfiltration channel.214- Private key files: `0600` permissions, a dedicated owner, outside the container image215 and outside the backup of the system they protect.216- Strict validation of the certificate/hostname pair in **every** client (SDKs included);217 disabling verification "temporarily" is a finding, even in development.218- Cryptographic dependencies: follow the CVEs of the TLS/crypto library in use and its support219 cycle (LTS vs non-LTS) — it is the component with the least tolerance for unpatched versions.220- Compliance: FIPS 140-3 replaces 140-2; the 140-2 certificates move to **Historical221 on 21-Sep-2026** (the systems keep working, but they stop counting for new222 federal acquisitions). If there is a requirement, verify the specific module in the CMVP, not the223 vendor's marketing claim.224225## 6. Operability226227- **Renewal is a service, not a task**: unattended ACME, process reload with no228 downtime (`nginx -s reload`, hot reload of the binary), and a periodic test that the reload229 really picks up the new certificate.230- The CA's rate limits (Let's Encrypt and equivalents) accounted for in the design: staging231 for tests, do not issue for every ephemeral deployment.232- Performance: TLS 1.3 with session resumption (careful with `0-RTT`: only for idempotent233 requests), OCSP stapling, and hardware acceleration where it exists. Software encryption234 is rarely the bottleneck; the **handshake** is.235- HSM/KMS: latency and the operations-per-second limit are plannable capacity (and236 cost). Cache unwrapped DEKs in memory with a TTL, never persist them in the clear.237- Observability: certificate expiry metrics, handshake failures by cause,238 negotiated version/suite, KMS errors and the renewal rate. Alert on symptoms239 (failed handshakes rising), not only on expiry.240- The clock: certificate validation depends on time. Reliable, monitored NTP; a clock241 drift presents itself as "TLS broken for no reason".242243## 7. Sustainability and prohibitions244245- **Cadence**: review password hashing parameters and TLS configuration at least246 annually (they rise with hardware) and the PQC plan **every six months** while the247 transition lasts. The reduction of certificate lifetimes forces a review of the automation each248 time a phase changes.249- Every exception (inherited RSA-2048, TLS 1.2 for an old client, GPG for a third party)250 carries an exit date and a ticket.251- Keep the **CBOM** alive, not as an annual export: it is the migration's work list.252253**FORBIDDEN**254- ❌ MD5 and SHA-1 with a security function; DES/3DES, RC4, ECB mode.255- ❌ Encryption without authentication (bare CBC/CTR) and improvised MAC-then-encrypt.256- ❌ Reusing a nonce/IV with the same key; a predictable IV or a global counter with no partitioning.257- ❌ Passwords with a fast hash (salted SHA-256/512), home-made schemes or hand-rolled rounds.258- ❌ A non-cryptographic PRNG for keys, tokens, salts, nonces or identifiers.259- ❌ Private keys or CA material in repos, images, artifacts or logs.260- ❌ RSA <3072 in new keys; ECDSA with a dubious RNG; PKCS#1 v1.5 for signing in new designs.261- ❌ TLS 1.0/1.1, suites without PFS, `InsecureSkipVerify`/`verify=False`/`--no-check-certificate`.262- ❌ HPKP; pinning without backup pins, without a kill switch or over third-party endpoints.263- ❌ Certificates issued or renewed by hand in production; a wildcard shared between unrelated services.264- ❌ An online root CA, with no name constraints and no revocation plan; an internal CA used for public surfaces.265- ❌ Backups whose key lives in the backed-up system, or with no tested restore.266- ❌ Implementing your own cryptographic primitives.267268### Quick review checklist269270- [ ] Algorithm and mode from the §2 table; nonce with an explicit strategy and a documented per-key limit.271- [ ] Passwords with Argon2id (or a justified alternative) and parameters verified this year.272- [ ] System randomness for every secret; constant-time comparisons.273- [ ] TLS 1.3 verified with `testssl.sh`; certificates via ACME with automatic renewal and an expiry alert.274- [ ] PKI with an offline root, intermediates by purpose, `nameConstraints` and a 24 h reissuance plan.275- [ ] Keys in a KMS/HSM with envelope encryption, key version alongside the data and tested rotation.276- [ ] Artifacts signed and verified at deployment; private keys outside repos and images.277- [ ] A CBOM generated in CI and a PQC plan with verified dates.278279## 8. Mandatory web verification280281Before committing to an algorithm, version, date or parameter in a deliverable:2822831. **NIST's PQC status**: FIPS 203/204/205 (and FIPS 206 / HQC), and the transition284 timeline of **NIST IR 8547** (RSA/ECC deprecation) and of **CNSA 2.0** by category.2852. **Maximum lifetime of public TLS certificates**: the current phase of the CA/Browser Forum's286 ballot SC-081 and the domain validation reuse periods.2873. **Hashing parameters** in the OWASP Password Storage Cheat Sheet (they change with288 hardware) and in the current revision of NIST SP 800-63B.2894. **Versions and EOL** of OpenSSL (or AWS-LC/BoringSSL), step-ca, cert-manager, `age`,290 restic/kopia/borg, cosign and `testssl.sh`, plus their open CVEs.2915. **Real support for PQC hybrids** in TLS (the exact group name, browsers, server)292 and in your KMS/HSM by region, before promising "quantum-safe".2936. **Your CA's news**: ACME profiles, ultra-short-lived certificates, changes in294 OCSP/CRL and rate limits.2957. **FIPS 140-3 validation** of the specific module in the CMVP if there is a compliance requirement.296297If the web contradicts this document, **the web wins** — flag the discrepancy.