Cryptography Fundamentals Questions
Core concepts and vocabulary of cryptography: confidentiality, integrity, authentication, and non-repudiation; the difference between symmetric and asymmetric primitives; and how standard algorithms, libraries, and protocols fit together. Covers threat models, common standards, and applying primitives and cryptographic libraries correctly to real-world security problems. The entry point for the cryptography track.
Give a high-level walkthrough of a TLS handshake: what happens at each step, which cryptographic primitives are used where (certificates, asymmetric key exchange, symmetric session keys, MAC/AEAD), and what properties TLS is actually trying to guarantee. What's one common way this can fail in practice?
Sample Answer
Direct answer
A TLS (Transport Layer Security) handshake lets a client and server who have never met agree
on a shared symmetric key, authenticate the server (and optionally the client), and start
exchanging data, with confidentiality, integrity, and (with modern configuration) forward
secrecy. It works by combining asymmetric key exchange and certificate-based identity checks
up front, then switching to fast symmetric encryption for the actual traffic.
Structured elaboration
sequenceDiagram
participant C as Client
participant S as Server
C->>S: ClientHello (supported versions, cipher suites, key share, random)
S->>C: ServerHello (chosen cipher suite, key share, random)
S->>C: Certificate (server public key, signed by a CA)
S->>C: Finished (proves possession of the certificate's private key)
Note over C,S: Both derive the same shared secret via ECDHE, then a session key via a KDF
C->>S: Finished (handshake integrity check)
C->>S: Application data (encrypted with the negotiated AEAD cipher)
S->>C: Application data (encrypted with the negotiated AEAD cipher)
- ClientHello / ServerHello: negotiate protocol version, cipher suite, and exchange
ephemeral key-exchange material (an elliptic-curve public value for ECDHE) plus random
nonces that feed the key derivation. - Certificate: the server presents its certificate, a public key bound to an identity and
signed by a certificate authority (CA), so the client can authenticate who it is actually
talking to (see PKI/certificate chains for how that trust is validated). - Key derivation: both sides combine the ECDHE exchange output through a KDF (key
derivation function) to produce the actual symmetric session keys, never sending the
session key itself over the wire. - Application data: all subsequent traffic is encrypted and authenticated with an AEAD
cipher (typically AES-GCM or ChaCha20-Poly1305) under the derived session key; older TLS
versions could instead pair a plain block cipher with a separate MAC (message
authentication code) computed over each record, a split that AEAD replaces with one
combined operation. - Properties TLS is guaranteeing: confidentiality (only the endpoints can read the data),
integrity/authenticity (tampering is detected), server authentication (the certificate
chain proves identity), and, with an ephemeral key-exchange suite, forward secrecy.
Worked example / common failure
The most common real-world failure is not a cryptographic break, it is trust management:
an expired certificate. Everything about the handshake's math can be flawless and the
connection will still be rejected (or a warning shown) the moment the leaf certificate's
validity window has passed, because clients check expiration as part of chain validation
before they will trust the negotiated key exchange at all. This is a frequent cause of
sudden, otherwise-unexplained outages, and is why certificate expiry monitoring is treated as
an operational, not just a security, concern.
Trade-offs & pitfalls
- TLS 1.3 (RFC 8446) simplified this flow and removed insecure options entirely (no more
static-RSA key exchange, no more weak cipher suites), which is why upgrading from TLS 1.2
is itself a meaningful security improvement, not just a version bump. - A valid, unexpired certificate chain proves identity, it does not by itself prove the
identity is trustworthy; certificate validation and business-level trust are separate
concerns.
Compare AES and DES/3DES: key and block sizes, why DES is considered insecure today, and what you'd need to consider when migrating a system that still has legacy DES-encrypted data.
Sample Answer
Direct answer
AES (Advanced Encryption Standard) uses a 128-bit block with 128, 192, or 256-bit keys and is
the current standard. DES (Data Encryption Standard) uses a 64-bit block with an effective
56-bit key, small enough to brute-force with commodity hardware today, which is why it is
considered broken. 3DES applies DES three times to stretch the effective key strength but
keeps DES's small 64-bit block, which is itself now a weakness.
Structured elaboration
- Key and block sizes: AES: 128-bit block, 128/192/256-bit key. DES: 64-bit block,
56-bit effective key (the stored key is 64 bits but 8 are parity bits). 3DES: same 64-bit
block, keying options up to an effective ~112-bit security level (not the naive 168 bits
three 56-bit keys would suggest, because of a known meet-in-the-middle attack against
simple triple encryption). - Why DES is insecure: a 56-bit keyspace is small enough that a dedicated brute-force
machine (the EFF's "Deep Crack" demonstrated this publicly in 1998) can exhaust it; modern
hardware makes this dramatically cheaper and faster. Separately, 3DES's 64-bit block is
small enough that encrypting large volumes of data under one key risks a birthday-bound
collision (the "Sweet32" attack), which is a practical concern even where the key itself is
not brute-forced. - Migrating legacy DES-encrypted data: you cannot just start writing new data with AES
and leave old DES ciphertext sitting there, since that ciphertext is only as strong as
DES's already-weak key. Decrypt each record with the legacy DES key inside a controlled,
audited process, re-encrypt it with AES-256-GCM under a freshly generated key, verify the
round trip before deleting the old ciphertext, and then securely destroy (zero out) the old
DES key material so it cannot be used to decrypt any remaining copies or backups.
Worked example
A payments system storing card-adjacent data under 3DES for a legacy compliance reason
migrates by: generating one new AES-256 key per data-encryption-key tier (following the same
envelope-encryption pattern used for any modern secret), running a batch job that reads each
3DES record, decrypts it in memory, re-encrypts with AES-256-GCM and a fresh nonce, writes
the new ciphertext, and only after a verified re-read does it mark the row migrated and
schedule the old key for destruction. Doing this as an in-place batch (rather than a
big-bang cutover) lets you roll back a partial migration if something goes wrong mid-run.
Trade-offs & pitfalls
- Backups and archives are the most commonly forgotten copies of DES-encrypted data during a
migration; the old key must be destroyed everywhere the ciphertext exists, or migrating the
live database accomplishes nothing. - 3DES is noticeably slower than AES (it runs the DES algorithm three times), which is
itself a good practical reason, beyond security, to retire it.
Define initialization vector (IV) and nonce as used in block/stream cipher modes. What properties must each satisfy (randomness vs uniqueness), and what happens in practice if a nonce is reused with a mode like GCM?
Sample Answer
Direct answer
An initialization vector (IV) or nonce ("number used once") is extra, non-secret input
combined with the key so that encrypting the same plaintext twice under the same key does not
produce the same ciphertext twice. Different cipher modes need different properties from it:
some need it unpredictable, all of them need it to never repeat under the same key. Reusing a
nonce with GCM is not a minor bug, it is a full break of that key's confidentiality and
authenticity.
Structured elaboration
- CBC mode: the IV should be unpredictable (ideally generated by a CSPRNG) and must never
repeat under the same key. It does not need to be secret, it is normally sent alongside the
ciphertext. - CTR and GCM modes: the nonce's essential property is uniqueness per key, not secrecy or
even unpredictability. GCM's internal encryption is CTR-mode-like: the nonce plus a
block counter generates a "keystream" that gets XORed with the plaintext. - Why nonce reuse under GCM is catastrophic: if the same key and nonce encrypt two
different messages, both use the identical keystream. XORing the two ciphertexts together
cancels the keystream out entirely, leaving the XOR of the two plaintexts, a classic
"two-time pad" break: an attacker who knows or guesses one plaintext immediately recovers
the other. GCM reuse is worse still: it can also expose the authentication subkey, letting
an attacker forge arbitrary valid messages for that key going forward.
Worked example
Say a reused keystream (from encrypting two different messages under the same key and nonce)
happens to be the bytes A5 3C 91 77. Encrypting "HELP" (48 45 4C 50 in hex) with it gives
ciphertext C1 = 48^A5, 45^3C, 4C^91, 50^77 = ED 79 DD 27. Encrypting "RUN!" (52 55 4E 21)
with the same keystream gives C2 = 52^A5, 55^3C, 4E^91, 21^77 = F7 69 DF 56. Now XOR the
two ciphertexts: C1 xor C2 = ED^F7, 79^69, DD^DF, 27^56 = 1A 10 02 71. That is exactly
"HELP" xor "RUN!" (48^52, 45^55, 4C^4E, 50^21 = 1A 10 02 71), with the keystream fully
canceled out. If an attacker already knows or can guess one plaintext ("HELP"), they recover
the other directly: M2 = M1 xor (C1 xor C2) = 48^1A, 45^10, 4C^02, 50^71 = 52 55 4E 21, which
decodes back to "RUN!". No key was ever recovered, and none was needed.
Trade-offs & pitfalls
- "Random" is a stronger property than "unique," but for GCM specifically, uniqueness is the
requirement that must never be violated; a random-but-short (96-bit) nonce chosen fresh
every time is standard practice precisely because random values are very unlikely to
collide at reasonable message volumes, not because randomness itself is the requirement. - A common real mistake is initializing a nonce counter to zero on every server restart or
every new connection, silently creating repeats across restarts or connections that share a
key.
Describe sources of randomness and entropy relevant to secure key generation in production systems. Compare hardware TRNGs, OS-provided CSPRNGs such as getrandom or /dev/urandom, and pitfalls of using non-cryptographic PRNGs or predictable seeding.
Sample Answer
Direct answer
Secure key generation needs randomness an attacker cannot predict or reproduce. Hardware true
random number generators (TRNGs) harvest genuine physical noise; operating-system CSPRNGs
(cryptographically secure pseudo-random number generators) mix that hardware entropy into a
pool and stretch it safely for applications to consume; ordinary, non-cryptographic PRNGs and
predictably-seeded generators are unsafe for key material because their output can be
predicted or reconstructed.
Structured elaboration
- Hardware TRNGs: derive bits directly from unpredictable physical phenomena, thermal
noise, electronic jitter, dedicated noise diodes on modern CPUs. These are a genuine entropy
source but are typically used to seed and periodically refresh a CSPRNG rather than being
read directly for every key, since a raw physical source can have subtle biases. - OS-provided CSPRNGs: the operating system maintains an entropy pool fed by hardware
sources plus unpredictable system events (interrupt timing, and similar), and exposes it
through an interface designed for cryptographic use, thegetrandom()system call on Linux,
or reading from/dev/urandom. Once the pool has been initialized (early in boot), these are
the correct, safe source for generating keys and nonces. - Pitfalls of non-cryptographic PRNGs: general-purpose generators like a language's
defaultrandom()(commonly a Mersenne Twister variant) are built for statistical spread in
simulations, not unpredictability against an adversary. Their internal state can often be
reconstructed from a modest number of observed outputs, after which every past and future
output becomes predictable, which is catastrophic if that generator ever produced a key or
nonce. - Pitfalls of predictable seeding: seeding any generator, including a good one, from a
low-entropy value like the current time in seconds collapses the effective search space to
the number of plausible seed values (how many seconds an attacker has to guess), letting
them brute-force the seed itself rather than the full key space, no matter how strong the
algorithm downstream looks.
Worked example, grounded in real incidents
The 2008 Debian OpenSSL bug (CVE-2008-0166) is the canonical case: a change intended to quiet
a memory-analysis warning accidentally removed most of the entropy sources feeding the
package's key generation, leaving only the process ID as effective variation. On Linux, that
reduced the practical keyspace for every SSH and TLS key generated on affected systems during
that window to roughly 32,768 possibilities, small enough to enumerate directly rather than
attack cryptographically. Separately, Sony's PlayStation 3 signing system reused the same
fixed value for the "random" nonce in every ECDSA signature it produced instead of generating
a fresh one each time; because ECDSA's security depends on that nonce never repeating, two
signed messages were enough for researchers to recover Sony's private signing key entirely.
Trade-offs & pitfalls
- The failure in both real incidents above was never a broken algorithm; OpenSSL and ECDSA
are both sound. The break was entirely in how randomness was sourced and used, which is
precisely why the sub-area matters even though it can feel like the "boring" part of a
cryptography question. - Do not reach for
Math.random(),random.random(), or similar in any language when
generating a key, nonce, or salt; use the CSPRNG interface your platform provides for
cryptography specifically.
Compare Message Authentication Codes (like HMAC or CMAC) with digital signatures: when would you use each for authentication and integrity, and how do they differ in non-repudiation, key management (shared vs asymmetric key), and performance in an enterprise setting?
Sample Answer
Direct answer
Use a MAC (like HMAC or CMAC) when both sides already share a secret key and you only need to
prove the message wasn't tampered with between two mutually-trusting parties. Use a digital
signature when you need non-repudiation, proof that a specific party and no one else produced
it, or when many independent parties need to verify without ever holding a shared secret.
Structured elaboration
- Non-repudiation: a MAC is computed with a shared key, so either party who holds that
key could have produced it; the receiver themselves is technically capable of forging a
valid MAC, which means a MAC can never prove who specifically created a message, even to
itself. A digital signature is produced with a private key only the signer holds; anyone
with the public key can verify it came from that specific private key, giving genuine
non-repudiation, the signer cannot credibly deny having signed it. - Key management: a MAC needs the same secret key securely distributed to every party who
must verify, which does not scale well once there are many independent verifiers. A
signature scheme needs one private key held by the signer and an openly distributable public
key; any number of parties can verify without any of them holding a secret at all, which is
why signatures fit enterprise settings with many downstream consumers (software distribution,
document signing across organizations, certificate chains). - Performance: HMAC (built from a hash function) and CMAC (built from a block cipher) are
both fast, symmetric-key operations. Signing with RSA or ECDSA costs more than computing a
MAC (it involves genuine asymmetric-key math), though ECDSA signing is considerably cheaper
than RSA signing at an equivalent security level; verification is typically the cheaper
half of a signature scheme.
Worked example
Two microservices inside the same trust boundary, sharing a secret deployed via the same
secrets manager, want to confirm requests between them are unmodified: HMAC is the right
choice, since both sides already trust each other and share the key, and no outside party
ever needs to verify these requests. A software vendor shipping an update that thousands of
independent customer machines must verify came from that vendor, and no one else, needs a
digital signature: there is no shared secret between the vendor and every customer, and only
the vendor's private key should be able to produce a valid signature.
Trade-offs & pitfalls
- Using a MAC where verification needs to happen outside the trusted pair (say, a
third-party auditor) quietly breaks the "who could have produced this" guarantee that the
scenario actually needed. - Using a signature purely for internal service-to-service integrity checks works but pays an
unnecessary performance and key-management cost when a shared-key MAC would have been
sufficient.
Unlock Full Question Bank
Get access to all 17 Cryptography Fundamentals interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.