Cryptography / Concepts

What Is Cryptography?

Cryptography is the mathematical and architectural discipline of securing data in transit and at rest over untrusted networks and storage environments. Standard encryption does not by itself protect data actively being processed—plaintext held in memory during computation is exposed to anyone with access to that memory or execution environment; protecting data in use typically requires separate techniques such as confidential computing enclaves or hardware-isolated execution, layered on top of the primitives described here. System evaluations begin by defining the required security property—Confidentiality, Integrity, Authenticity, or Non-Repudiation—and selecting reviewed, standardized algorithms and protocols that enforce those properties under explicit threat models.

The Open Network Threat Problem

In an untrusted network environment (such as the public internet), raw data packets passing across transit routers are vulnerable to several attack classes. The three below are network-observable attacks with a direct cryptographic countermeasure; this is a simplified, journal-created grouping for orienting the properties below, not an exhaustive or standards-defined taxonomy of network threats:

Network threats mapped to cryptographic objectives: eavesdropping to confidentiality, tampering to integrity, and impersonation to authenticity.

A simplified, journal-created grouping of three network-observable attacks and their primary cryptographic countermeasure — not an exhaustive threat taxonomy. The three properties are independent, not sequential; the connecting arrows are a layout device, not a causal or ordering claim.

  1. Eavesdropping (Passive Attack): An adversary intercepts and reads sensitive message payloads (Violates Confidentiality).
  2. Tampering (Active Attack): An adversary alters bit sequences within transit packets (Violates Integrity).
  3. Impersonation (Active Attack): An adversary spoofs sender identity, injecting malicious instructions under a trusted identity (Violates Authenticity).

A fourth concern, repudiation — a sender denying they originated a high-value instruction after the fact — is not a network-observable attack in the same sense as the three above; it’s an operational and evidentiary problem that non-repudiation mechanisms (signatures, timestamping, custody logs) address after the communication has already happened, which is why it isn’t pictured in the diagram alongside the three transit-level attacks.

Cryptography provides mathematical primitives designed to withstand these attack classes even when the network infrastructure is completely controlled by an adversary — but it does not by itself solve every threat to network communication: availability/denial-of-service, traffic analysis (an observer learning who is talking to whom, and how much, even without reading payload content), and compromise of an endpoint or its keys are all threats cryptography alone does not close. RFC 9846’s security considerations discuss residual traffic-analysis and implementation risk that remain even with TLS 1.3 correctly deployed.

The Four Core Cryptographic Security Properties

Property Core Operational Goal Primary Cryptographic Primitive Failure Scenario Without Control
Authenticity Verifies that data originated from an entity controlling a specific key Digital Signatures (Ed25519, FIPS 204 ML-DSA) & Public Key Infrastructure (PKI) Man-in-the-middle impersonation and payload spoofing
Confidentiality Restricts payload reading exclusively to authorized key holders Symmetric Ciphers (AES-128-GCM / AES-256-GCM, ChaCha20-Poly1305) encrypt the actual payload; Key Encapsulation Mechanisms (KEMs) (FIPS 203 ML-KEM, hybrid X25519MLKEM768) don’t encrypt payload data themselves — they establish the shared keying material a KDF and AEAD then use to do so, the composition RFC 9180 HPKE formalizes as KEM + KDF + AEAD Cleartext exfiltration of PII, passwords, or financial transactions
Integrity Ensures payload modification or bit-rot is detected against a digest obtained through a trusted channel Cryptographic Hashes (SHA-256, SHA3-256) for accidental corruption; MACs (HMAC-SHA256) when an adversary may control the data Unauthorized alteration of database fields or transaction amounts
Non-Repudiation Generates cryptographic evidence, computationally unforgeable under the signature scheme, tying an action to a private key—supporting but not by itself constituting legal non-repudiation Asymmetric Digital Signatures (Ed25519, FIPS 205 SLH-DSA) with timestamping and key custody logs Disavowal of financial commitments or administrative actions

An unkeyed hash only detects change when the verifier compares against a digest obtained through a channel the attacker cannot also tamper with (e.g., a value published separately or embedded in a signed document). An attacker who can replace both the data and its accompanying digest simply recomputes the hash over the modified data, so the check silently passes. Detecting unauthorized alteration by an adversary who controls the channel requires a keyed construction—a MAC or a digital signature—not a bare hash.

Formal Security-Notion Vocabulary

The properties above (Authenticity, Confidentiality, Integrity, Non-Repudiation) are the practitioner-level names; the cryptography literature — and the standards this section cites throughout — defines more precise formal notions for exactly what “secure” means for a given primitive, expressed as games an adversary is assumed to try to win:

These notions matter because “secure” is not a single property — a scheme can satisfy one and fail another (unauthenticated AES-CBC is IND-CPA-secure in the right mode but has no ciphertext integrity at all), and knowing which notion a given standard or RFC claims to satisfy is what lets you check whether it actually covers your threat model.

Real-World Protocol Composition: How TLS 1.3 Combines Primitives

Production security protocols rarely rely on a single cryptographic primitive. Instead, they combine primitives into a cohesive architecture.

For example, TLS 1.3 (RFC 9846, which obsoletes the original RFC 8446) coordinates primitives across three phases in its most common configuration — a full handshake authenticated by an X.509 certificate. TLS 1.3 also supports PSK-only and PSK-plus-ephemeral-DH resumption modes, which omit the Certificate/CertificateVerify messages entirely, and separately supports raw public keys in place of certificates (RFC 7250); the flow below is the certificate-authenticated case, not every valid TLS 1.3 handshake:

TLS cryptographic layers for server authentication, shared-secret establishment, and authenticated encryption of application data.

The common certificate-authenticated TLS 1.3 handshake — PSK-only and PSK-plus-ephemeral-DH resumption modes skip certificate authentication, and raw public keys are also a valid alternative to certificates

  1. Authentication: In the certificate-authenticated case shown here, the server proves ownership of a public key bound to a domain via an X.509 Certificate issued by a trusted CA.
  2. Ephemeral Key Establishment: Peer endpoints use an ephemeral group such as X25519 or the hybrid X25519MLKEM768 group defined in RFC 10024, a separate specification from the base TLS 1.3 RFC. X25519 combines two Diffie-Hellman contributions; X25519MLKEM768 combines an X25519 result with an ML-KEM shared secret before the TLS key schedule derives traffic secrets. Neither construction transmits a private key or a pre-existing traffic key.
  3. AEAD Bulk Encryption: TLS 1.3 requires implementations to support AES-128-GCM (mandatory-to-implement) and commonly negotiates AES-256-GCM or ChaCha20-Poly1305; the standard also defines AES-CCM cipher suites for constrained environments (RFC 9846 §9.1), so “GCM or ChaCha20-Poly1305” describes the common case, not every valid TLS 1.3 negotiation.

Cryptographic Randomness: Pseudo-Random Number Generators (PRNG) vs. Cryptographically Secure PRNGs (CSPRNG)

Cryptographic security depends on randomness, but not every value needs the same property from it, and the requirement depends on the specific construction, not the value’s category alone. A Pseudo-Random Number Generator (PRNG) is any deterministic algorithm that expands a seed into output that looks random; a Cryptographically Secure PRNG (CSPRNG) is a PRNG specifically designed so that output is unpredictable to anyone who doesn’t know its internal state. Randomly generated keys and bearer secrets (session tokens, API tokens) need unpredictability — an adversary must not be able to guess the value in advance, which is why a value produced this way needs a CSPRNG. That’s a statement about the origin of a randomly generated value, not a claim that every key or token must be direct CSPRNG output: a key can instead be securely derived from another key (KDF), password-derived, or established through key agreement (see Secure Key Generation & Provisioning), and a token can be a self-contained signed or MACed object rather than a random opaque bearer handle — both are valid origins with their own separate security requirements. AES-GCM’s IV requirement is fundamentally uniqueness under a given key, not unpredictability: NIST SP 800-38D §8.2 defines two valid IV constructions — a deterministic construction (a fixed field plus an invocation counter) and an RBG-based construction (an IV generated by a Random Bit Generator, i.e., randomly, which needs a CSPRNG both for unpredictability and to keep the collision probability of repeating an IV acceptably low at 96 bits). Neither construction gets uniqueness for free: the deterministic construction is unique only if the design actually enforces it — correct per-key/per-device/per-context partitioning of the counter’s namespace, counter state that survives restarts and snapshots instead of resetting, handling for counter exhaustion, and key rotation before that happens; the RBG-based construction remains probabilistic and is bound by NIST SP 800-38D §8.3’s per-key invocation limit (2^32 encryptions for the 96-bit random-IV construction), not an unconditional guarantee — see the AEAD Operational Limits table on the Symmetric Cryptography page for the full numeric bounds. Either construction is valid GCM usage; a random IV is common practice, but “IVs must be unpredictable” overstates GCM’s actual requirement. Many nonces in other constructions and password-hashing salts require only uniqueness, not unpredictability — a monotonic counter is a perfectly good nonce for constructions built to expect one, and a password-hashing salt’s job is to be distinct per record, not to be unguessable; other salt-like values are a different case — an HKDF salt, for instance, may be fixed or reused, since it serves the extract stage’s role rather than a per-record uniqueness one (RFC 5869). Conflating “must be unique” with “must be random” glosses over this: use a CSPRNG when unpredictability is the actual requirement (a randomly generated key, bearer token, or a chosen random-IV construction), and don’t assume every uniqueness requirement needs one.

PRNG vs. CSPRNG Comparison

Generator Class Internal Mechanics Security Properties Target Application Use Case
Non-Cryptographic PRNG Fast deterministic algorithms (Linear Congruential Generators, Mersenne Twister). INSECURE: Observing enough outputs may permit full internal-state recovery, letting an attacker predict all future values — the number of outputs needed depends on the generator (a simple LCG can fall from just a couple of outputs; MT19937 needs 624 consecutive 32-bit outputs, as the simulator below demonstrates). Game physics, Monte Carlo simulations, UI shuffling. (Do NOT use for security).
CSPRNG (Cryptographically Secure PRNG) “CSPRNG” is used at two different levels in practice, and it’s worth keeping them apart: the deterministic expansion mechanism itself — a Deterministic Random Bit Generator (DRBG) construction such as Hash_DRBG, HMAC_DRBG, or CTR_DRBG per NIST SP 800-90A — versus the complete, entropy-backed OS-level service applications actually call (getrandom(), os.urandom()). NIST’s own architecture separates these further still: SP 800-90B defines the entropy source, SP 800-90A defines the DRBG mechanism that expands it, and SP 800-90C defines the Random Bit Generator (RBG) construction that combines an entropy source with a DRBG into the complete generator an application actually uses. The specific underlying primitive is implementation-dependent (e.g., Linux’s kernel CSPRNG is ChaCha20-based, not necessarily SHA-256 or AES-CTR-DRBG). SECURE when properly seeded, constructed, and operated — not from seeding alone: it satisfies Next-Bit Unpredictability provided the entropy source supplies sufficient min-entropy at initialization, but the specific DRBG construction, protection of its internal state, correctness of the implementation, per-request/per-reseed output limits, and the platform’s reseed policy all factor into whether a given instance is actually secure, separate from whether it was seeded at all. Backtracking Resistance (state compromise cannot reveal past outputs) is a property of the specific DRBG construction—the SP 800-90A Hash_DRBG, HMAC_DRBG, and CTR_DRBG designs provide it, but it is not automatic for every CSPRNG implementation. Generating AES keys, RSA/ECC key pairs, IVs, and randomly generated bearer tokens (see the salt discussion above for why salts aren’t a blanket CSPRNG requirement).
Randomness Pitfalls & Language API Guide
The Math.random() Vulnerability & Secure CSPRNG APIs

Using standard non-cryptographic random functions (such as JavaScript Math.random() or Python's random module) to generate API tokens or session identifiers is unsafe: an attacker who can observe enough of the generator's raw output can, for many such PRNGs, reconstruct its internal state and predict or forge subsequent values, enabling session hijacking or account takeover. The exact number and form of observations needed is generator- and API-specific — the simulator below recovers Python's MT19937 state from 624 consecutive, complete, raw 32-bit outputs with no intervening draws; a transformed value such as a bounded integer (random.randint()), a float (random.random()), or an encoded token string consumes generator output through additional steps (rejection sampling, combining multiple words) and isn't simply interchangeable with a raw 32-bit word for this specific attack, though the underlying state is no more secure for having been transformed. Cryptographic nonces are a separate case with construction-specific requirements rather than one blanket rule: GCM nonces need only be unique per key (a non-cryptographic monotonic counter can satisfy that), while CBC IVs additionally need to be unpredictable — see the Uniqueness vs. Unpredictability discussion below for which requirement applies to which construction:

  • Node.js / Web Browsers: Replace Math.random() with crypto.randomBytes(32) or crypto.getRandomValues().
  • Python: Replace random.choice() with secrets.token_bytes(32) or os.urandom().
  • Java: Replace java.util.Random with java.security.SecureRandom — the underlying provider and algorithm are implementation-specific, and automatic/explicit reseeding support varies by provider, so verify the target JDK's actual behavior rather than assuming it (see the Java SE SecureRandom documentation).
  • Linux Kernel / OS Source: Use getrandom() system call, /dev/urandom, or Windows BCryptGenRandom().

Entropy Sources, DRBG Architecture & Reseeding

A CSPRNG is not itself a source of randomness — it’s a deterministic expansion algorithm that stretches a small amount of genuinely unpredictable input (entropy) into a long stream of output bits, though not an unbounded one: SP 800-90A DRBGs specify a maximum number of bits servable per request and a maximum total output before a mandatory reseed (see Reseeding below), so “long” means long enough for practical use within those limits, not literally arbitrary. Where that entropy comes from, and how the generator’s internal state is maintained over the life of a process, determines whether the “cryptographically secure” label actually holds in practice.

Client-Side Simulator: Insecure PRNG (MT19937) State Reconstruction Attack

This simulator specifically models MT19937, the generator behind Python’s random module. Given 624 consecutive, complete, raw 32-bit outputs with no draws hidden or dropped in between, an attacker can reconstruct its internal state and predict the immediate next output — the demonstration below shows one such prediction, not an unlimited stream, though the reconstructed state does let the attacker continue predicting further outputs the same way. Browser Math.random() is also non-cryptographic, but its algorithm is implementation-dependent per the ECMAScript specification and is not necessarily MT19937 — V8 (Chrome/Node.js), for instance, uses xorshift128+, a different algorithm this specific attack does not target — see V8’s own explanation of its Math.random() implementation:

Interactive Exploit Simulator

Insecure PRNG (MT19937) State Reconstruction Attack

Demonstrates how an adversary observing 624 consecutive, complete, raw 32-bit outputs from a non-cryptographic PRNG (Mersenne Twister MT19937) — with no draws hidden or dropped in between — inverts the tempering operations, reconstructs the 624-word internal state, and correctly predicts the generator's next raw output. "Password-reset token" here illustrates the consequence of the underlying vulnerability (a fully reconstructable internal state), not a claim that real-world tokens are literally raw MT19937 words — the number of observations an attacker actually needs against a real token depends on how that token encodes the generator's output.

Target PRNG Server (Observed Tokens 1 - 624)
Click "Generate Target PRNG Tokens" to begin.
Attacker State Predictor (Untempered Reconstruct)
Awaiting 624 target tokens...

Cryptographic Implementation Attacks

Correct math doesn’t guarantee a correct implementation. A cipher, signature scheme, or KDF proven secure against an idealized adversary can still leak its secrets through how the code that implements it actually runs on real hardware — a distinct attack surface from the algorithm’s mathematical design.

Safe Protocol Composition

Individually secure primitives can combine into an insecure protocol if the composition doesn’t account for a few recurring failure patterns:

Practical Cryptographic Implementation Guidelines

What I need to remember

Never invent custom cryptography — use standardized, peer-reviewed primitives, a CSPRNG for values that genuinely need unpredictability, and AEAD by default for new symmetric encryption. Design for cryptographic agility and account for how long encrypted data must stay confidential, including post-quantum migration.

Primary references