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.
Compare block cipher modes of operation such as CBC and GCM. In a system that requires encryption for disks (at-rest logs) and for transport (TLS-like traffic), which mode(s) would you choose for each use case and why? Discuss IV/nonce requirements and integrity guarantees.
Sample Answer
Direct answer
For transport-like traffic (a live connection between two parties), use Galois/Counter Mode (GCM): it is authenticated, single-pass, and parallelizable, which matches a stream of packets where you want low latency and can generate a fresh nonce per message easily. For data at rest (logs sitting on disk with no live connection to negotiate per-message nonces), Cipher Block Chaining (CBC) is the classic textbook answer but is the wrong choice today for the same reason it always was: it provides no built-in integrity check. The honest, current recommendation for both cases is an authenticated mode, GCM (or an alternative authenticated construction) for both, with the at-rest case leaning on deliberate nonce management rather than live negotiation.
Comparing the modes
- CBC encrypts each plaintext block XORed with the previous ciphertext block, using an initialization vector (IV) to seed the first block. It needs the IV to be unpredictable (not necessarily secret, but not attacker-guessable in advance) and requires padding, which historically enabled padding-oracle attacks when an application leaked whether decryption padding was valid. Critically, CBC on its own gives you confidentiality but no integrity: an attacker can flip bits in ciphertext and produce predictable, attacker-influenced changes in the decrypted plaintext with no error raised.
- GCM combines counter-mode encryption with a polynomial-based authentication tag (GHASH) in one pass, so it gives you both confidentiality and integrity, and it detects any tampering by failing to verify rather than silently decrypting corrupted data. Its hard requirement is a nonce (a 96-bit value in the standard construction) that must never repeat under the same key, reuse breaks both the confidentiality guarantee (via keystream reuse) and the authentication guarantee (via leaking GCM's internal authentication key), so nonce uniqueness is non-negotiable.
Worked recommendation
- At-rest logs: use GCM, with nonces generated from a per-file or per-segment counter that is durably persisted alongside the encrypted data (so a process restart cannot repeat a value), or a per-record random 96-bit nonce if record volume per key stays well under the birthday-bound guidance for random nonces. Store the nonce and authentication tag next to the ciphertext; verification on read means corrupted or tampered log segments are detected immediately instead of silently trusted.
- Transport-like traffic: use GCM (or ChaCha20-Poly1305 where hardware AES acceleration isn't available) with a fresh, connection-scoped nonce per record, which is exactly the pattern Transport Layer Security (TLS) 1.2 and 1.3 use internally, a per-record explicit or implicit nonce derived from a sequence number.
Trade-offs and pitfalls
The single hardest constraint in both cases is the same one: nonce uniqueness under a fixed key. Choosing GCM for both use cases only pays off if the nonce-generation strategy for each is actually enforced (durable counters for files that survive restarts, connection state for transport), because a mode swap from a broken CBC deployment to a broken GCM deployment (repeating nonces) is not actually a fix, it trades one class of catastrophic failure for another.
Describe Public Key Infrastructure (PKI) fundamentals: what a certificate is, what a Certificate Authority (CA) does, certificate chains and trust anchors, and a typical use of certificates in TLS. Keep the explanation high-level but include how trust is established and how certificate expiration affects secure channels.
Sample Answer
Direct answer
Public Key Infrastructure (PKI) is the system of certificates, certificate authorities, and
trust chains that lets a stranger's public key be trusted without meeting them first. A
certificate authority (CA) signs a certificate binding a public key to an identity; anyone who
already trusts that CA can then trust the certificate, and by extension the key inside it.
Structured elaboration
flowchart TD
Root["Root CA (trust anchor, pre-installed in OS/browser)"]
Inter["Intermediate CA (signed by Root)"]
Leaf["Server certificate (signed by Intermediate)"]
Root -->|signs| Inter
Inter -->|signs| Leaf
Leaf -->|presented during TLS handshake| Client["Client validates the whole chain"]
- Certificate: a data structure containing a public key, an identity (like a domain
name), a validity window, and a signature from whoever issued it. - Certificate authority (CA): a party trusted to verify identity claims before signing a
certificate. Trust in a CA is not proven cryptographically from scratch each time, it comes
from the CA's root certificate being pre-installed as a trust anchor in operating systems
and browsers. - Certificate chains: in practice, a root CA rarely signs end-entity (leaf) certificates
directly; it signs intermediate CAs, which sign the leaf certificates servers actually
present. Validating a certificate means walking this chain, checking each signature, until
reaching a root the client already trusts. - Use in TLS: during the handshake, the server presents its certificate (and usually the
intermediate chain); the client verifies the signature chain up to a trusted root, checks
the domain name matches, and checks the validity window, before it will trust the public
key for the key exchange.
Worked example
A browser connecting to example.com receives a leaf certificate for example.com signed by
"Intermediate CA X," which is itself signed by "Root CA R." The browser already has Root CA
R's certificate baked into its trust store. It verifies Intermediate CA X's signature using
Root CA R's public key, then verifies the leaf certificate's signature using Intermediate CA
X's public key. Only after both signatures check out, the domain name matches, and the
current date falls inside the leaf certificate's validity window does the browser proceed to
trust that public key for the handshake.
Trade-offs & pitfalls
- Certificate expiration: every certificate in the chain has a validity window; if the
leaf certificate's window ends and it is not renewed, clients will refuse the connection (or
warn loudly) even though nothing about the underlying keys has actually changed. This is a
frequent, entirely avoidable cause of production outages, which is why certificate expiry is
tracked as an operational alert, not just a one-time setup step. - Self-signed certificates skip the CA entirely (the certificate signs itself), which is fine
for internal testing but provides no independent identity verification for anyone who
hasn't been told in advance to trust that specific certificate.
Describe how you would perform a cryptographic library audit to find misuse (e.g., incorrect mode selection, improper padding, insecure defaults). What static and dynamic analysis tools or test vectors would you use, and how would you prioritize remediation across findings that vary in exploitability?
Sample Answer
Direct answer
Treat a cryptographic library-misuse audit as two separate lanes that feed each other: static analysis to find suspicious call sites at scale, and dynamic, test-vector-driven analysis to prove which of those sites are actually exploitable. Then triage findings by exploitability and blast radius, not by file order or how alarming a finding looks in isolation.
What "misuse" looks like
- Wrong mode selection: ECB mode used for anything beyond a single block. ECB encrypts identical plaintext blocks to identical ciphertext blocks, so repeated structure in the plaintext (a bitmap, a repeated field) leaks straight through the ciphertext.
- Improper padding: a custom padding-validation routine whose error path (message, timing, or response code) differs depending on whether the padding was well-formed, the classic padding-oracle shape that lets an attacker decrypt ciphertext byte by byte through repeated queries.
- Insecure defaults: a library or wrapper that ships a default IV of all zeros, a default weak cipher, or a key size that's fine for a demo but not for production, and a caller who never overrides the default inherits the weakness silently.
Static analysis
Pattern- and AST-based scanners (for example Semgrep with a crypto-focused ruleset, or a language's own security linter such as Bandit for Python) can flag known-bad call shapes directly: Cipher(..., modes.ECB()), a broken digest like MD5 used outside a non-security checksum context, or a byte-array key or IV that's a literal constant in source. Secret-scanning tools (gitleaks, truffleHog) catch hardcoded keys specifically. General static analysis (CodeQL and similar) adds language-wide security query packs beyond crypto-specific ones.
Dynamic and test-vector analysis
Run the code path that actually performs encryption/decryption against known-answer test vectors, Google's Project Wycheproof is built exactly for this: it contains adversarial test vectors (weak IVs, invalid curve points, edge-case moduli) specifically designed to catch the misuse classes above rather than just confirming a library works on "normal" input. Pair that with differential testing against a reference implementation on the same inputs, and fuzz the parsing and validation code paths that handle ciphertext or padding, since those are exactly where a padding-oracle-shaped bug tends to live.
Prioritizing remediation
Score every finding on two axes: exploitability (is the vulnerable path reachable by an unauthenticated network attacker, or only by someone who already has local code execution) and impact (does it break confidentiality of data at rest, or fail loudly and safely). Fix network-reachable, confidentiality-breaking findings first regardless of how small or old the code looks; track lower-exploitability findings on a remediation backlog with a deadline weighted by that same exploitability score, rather than by severity label alone.
Worked example
The ECB pattern leak, demonstrated directly:
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
import os
key = os.urandom(32)
block = b"AAAAAAAAAAAAAAAA" # one AES block (16 bytes), repeated
plaintext = block * 4
encryptor = Cipher(algorithms.AES(key), modes.ECB()).encryptor()
ciphertext = encryptor.update(plaintext) + encryptor.finalize()
blocks = [ciphertext[i:i + 16] for i in range(0, len(ciphertext), 16)]
print("all four ciphertext blocks identical:", blocks[0] == blocks[1] == blocks[2] == blocks[3])
Output:
all four ciphertext blocks identical: True
Four identical plaintext blocks produce four identical ciphertext blocks under ECB, exactly the structural leak that static-analysis rules are built to flag before the code ever ships.
Trade-offs and pitfalls
Static analysis alone produces false positives (a "bad" call inside a well-reviewed wrapper that's actually fine) and false negatives (a config-gated insecure default that's only reached through a rarely-used flag), so treat its hits as leads, not verdicts. Test-vector and fuzzing analysis alone will miss anything the vectors and fuzz corpus don't exercise. And both together still miss pure logic-level misuse, the right function called with the wrong parameters, such as a correct AEAD (Authenticated Encryption with Associated Data) call with a caller-supplied fixed nonce, which usually needs a manual review pass on the highest-risk call sites even after tooling runs clean.
Describe how the Elliptic Curve Digital Signature Algorithm (ECDSA) works at a high level, why ECDSA signatures can be malleable in some formats, and what best practices you would enforce when verifying and storing ECDSA signatures in a distributed system.
Sample Answer
Direct answer
The Elliptic Curve Digital Signature Algorithm (ECDSA) signs a message by picking a random
per-signature value, turning it into a curve point, and combining that with the message hash and
the private key to produce a pair of numbers, (r,s). Those signatures can be malleable, meaning
a different valid signature can be produced for the same message without the private key,
because for every valid (r,s) the pair (r,n−s), where n is the curve's group order, is
also valid. Distributed systems must enforce a canonical form on ingestion or that second, forged
signature can be mistaken for a distinct, unrelated event.
Structured elaboration
- How it works, at a high level. Hash the message, generate a fresh random nonce k, compute
the curve point k⋅G and take its x-coordinate mod the group order n as r, then
compute:
where d is the private key. Verification recomputes a point from (r,s,H(m),public key) and checks that its x-coordinate matches r.
- Why malleability exists. The verification equation is symmetric under negating s: both s
and n−s satisfy it for the same (r,H(m),public key). Different byte encodings
(raw r∥s versus Distinguished Encoding Rules, DER) add a second, unrelated source of
malleability, since a non-canonical Abstract Syntax Notation One (ASN.1) encoding can represent
the identical logical signature as more than one byte string. - Real-world impact. This is not theoretical: Bitcoin's original protocol computed a
transaction's identifier from its raw serialized bytes, signature included, so anyone could flip
s→n−s on an unconfirmed transaction and change its identifier without invalidating it,
a bug generally referred to as transaction malleability, later addressed by enforcing low-s
signatures and, more completely, by Segregated Witness.
Worked example
This is directly demonstrable, not just asserted, by generating a real key pair, signing once, and
checking that both the original and the flipped signature verify:
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature, encode_dss_signature
from cryptography.hazmat.primitives import hashes
from cryptography.exceptions import InvalidSignature
private_key = ec.generate_private_key(ec.SECP256R1())
public_key = private_key.public_key()
n = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551 # NIST P-256 group order
message = b"transfer 100 units to account 42"
signature = private_key.sign(message, ec.ECDSA(hashes.SHA256()))
r, s = decode_dss_signature(signature)
s_flipped = (n - s) % n
flipped_signature = encode_dss_signature(r, s_flipped)
def verifies(sig):
try:
public_key.verify(sig, message, ec.ECDSA(hashes.SHA256()))
return True
except InvalidSignature:
return False
print("original signature verifies: ", verifies(signature))
print("(r, n - s) signature also verifies:", verifies(flipped_signature))
print("exactly one of {s, n-s} is low-S (<= n/2):", (s <= n // 2) != (s_flipped <= n // 2))
original signature verifies: True
(r, n - s) signature also verifies: True
exactly one of {s, n-s} is low-S (<= n/2): True
That third line is the useful, always-true invariant across runs (the nonce is random, so which of
the two happens to be "original" varies, but exactly one member of every {s,n−s} pair is
always ≤n/2), and it is exactly what the low-S rule below relies on.
Trade-offs & pitfalls
- Enforce canonical form on ingestion. Require strict DER parsing (reject non-minimal
encodings), and enforce the low-S rule, only accept signatures where s≤n/2, canonicalizing
or rejecting the high-S alternative. Reject r=0 or s=0 outright. - Verify the public key, not just the signature. Confirm the public key actually lies on the
curve and is not the point at infinity before using it, and prefer deterministic nonce generation
(RFC 6979) over a naive random nonce, since a reused or biased nonce leaks the private key
entirely, a different and more severe failure than signature malleability. - Storage and audit. Store signatures immutably alongside signer key identifier, algorithm,
timestamp, and canonicalization status, so a non-canonical or unexpected encoding is itself a
signal worth alerting on, not just silently rejecting. - Common wrong turn: deriving an event's identity or deduplication key from the raw signature
bytes instead of from the signed message content; that is precisely the design flaw malleability
exploits.
What is authenticated encryption (AEAD) in practical terms? Describe the API shape (plaintext, associated data, nonce in; ciphertext and authentication tag out), the security properties it provides, and give a concrete example of an attack that becomes possible if you use plain (unauthenticated) encryption instead.
Sample Answer
Direct answer
Authenticated encryption (AEAD, authenticated encryption with associated data) is encryption
that also proves the ciphertext was not tampered with. The API takes plaintext, a nonce (a
number used once), and optional associated data (AD, extra context that must be visible and
authenticated but not itself encrypted, like a protocol version byte); it returns ciphertext
plus an authentication tag. On decrypt, if the tag does not verify, you get no plaintext at
all, not a corrupted one.
Structured elaboration
- Inputs: plaintext, a nonce (unique per encryption under a given key, does not need to
be secret), and associated data (AD): data you want authenticated but left in cleartext,
for example a message header or routing metadata a middlebox needs to read. - Outputs: ciphertext (same length as the plaintext) and an authentication tag (a fixed
size, typically 16 bytes for AES-GCM), which travels alongside the ciphertext. - Security properties: confidentiality of the plaintext, and integrity/authenticity of
both the ciphertext and the associated data. Decryption is a single atomic operation:
verify the tag first, and only release plaintext if it matches. Common real
implementations are AES-GCM and ChaCha20-Poly1305.
Worked example
Contrast this with plain, unauthenticated encryption, say AES in CBC mode (CBC, Cipher Block Chaining, is a mode that splits the data into fixed-size chunks called blocks and chains each block onto the previous one) with no separate
integrity check. CBC decryption XORs each ciphertext block with the previous ciphertext block
(or the IV for the first block, where IV means initialization vector, a random starting block used because the very first block has no previous ciphertext block to chain onto) after a block-cipher decrypt (a block cipher, such as AES, is the core algorithm that transforms one fixed-size block at a time). An attacker who can flip bits in
a ciphertext block causes a predictable, corresponding bit flip in the next decrypted
plaintext block, with no error raised, because CBC decryption has no way to detect tampering
on its own. This is the mechanism behind real padding-oracle attacks (Vaudenay's 2002 attack,
and the 2014 POODLE attack on SSLv3's CBC handling): by sending crafted ciphertexts and
watching whether the server complains about bad padding, an attacker recovers the plaintext
one byte at a time without ever learning the key. AEAD closes this off structurally: any bit
flip anywhere in the ciphertext or associated data changes the tag, so a tampered message is
rejected before any plaintext is returned, and there is no padding-error side channel to
probe in the first place.
Trade-offs & pitfalls
- AD is authenticated but not confidential: do not put anything secret in it expecting
encryption; it is meant for routing/context fields that must stay legible. - Reusing a nonce under the same key breaks the security guarantee entirely for most AEAD
modes (this is worse for GCM specifically, where it can also leak the authentication
subkey). - "Encrypt, then separately compute an HMAC yourself" (encrypt-then-MAC) achieves the same
goal as AEAD but pushes the correctness burden onto you; AEAD ciphers bundle it so there is
one call to get right instead of two to sequence correctly.
Unlock Full Question Bank
Get access to all Cryptography Fundamentals interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.