skip to content

Encryption keys, initialisation vectors, nonces, password salts and session identifiers are all commonly produced by "generate some random bytes." For each of these, state which property the consumer actually requires — unpredictability, uniqueness, or both — and explain what concretely breaks when the wrong property is supplied.

level: middleimportance: should knowfreq 45%

answer

  1. property first, generator second
  2. counter = unique, predictable
  3. random = unpredictable, only probably unique
  4. salt: unique, public, per record
  5. nonce reuse and shared salts fail silently

basics

~20 s

Randomness is a means, not the requirement. Keys and tokens need unpredictability. Nonces need uniqueness — a counter is often better. Salts need uniqueness, not secrecy. Some IVs need unpredictability too. Naming the required property tells you which generator, and how many bits.

solid answer

~50 s

Ask what the consumer's contract is, then pick a source that satisfies it. - **Keys**: full unpredictability, full length. Anything less collapses the key space to what the attacker can enumerate. - **Session ids, reset/invite/API tokens, CSRF values**: unpredictability plus enough length to survive online guessing; uniqueness follows from length. - **Nonces for a counter-style mode**: *uniqueness under one key* is the contract, and a monotonic counter satisfies it perfectly while a random draw only satisfies it probabilistically (the birthday bound bites for short nonces). Unpredictability is not required. - **Some chaining modes' IVs**: uniqueness is not enough — a predictable next IV enables chosen-plaintext distinguishing, so those need unpredictability. The mode's own documentation, not folklore, states which. - **Password salts**: uniqueness per record; they are stored in the clear alongside the hash, so secrecy is not the point — defeating precomputed and shared work is. Getting this backwards produces silent failures: a repeated nonce, a shared salt, or a guessable token all keep working perfectly.

go deeper

for a junior

Be able to split the list into two piles: values an attacker must not guess (keys, session ids, reset tokens) and values that only need to be different each time (nonces, salts). Say that salts are stored in the open.

for a middle

Name the property per consumer and give one concrete consequence each: guessable token equals account takeover, repeated nonce breaks the mode's guarantee, shared salt restores precomputation. Mention that a counter beats randomness for uniqueness.

for a senior

Bring in the birthday bound for random nonce sizing, the chosen-plaintext argument for unpredictable IVs, and the operational reason counters are hard in practice (restarts, replicas, clones). Stress the silence of all these failures.

for a principal

Turn it into a design rule: every generated value in the system gets its required property written down at the point of design, the generator is chosen from that property, and non-security uses are separated so the fast generator is never reachable from the security path.

## Why "just use random bytes" is the wrong mental model "Random" is not a requirement; it is one implementation of two different requirements. When you write down which one a value actually needs, three practical decisions fall out immediately: which generator to draw from, how many bits to draw, and whether a non-random construction would be *better* than randomness. The two properties: - **Unpredictability**: an attacker who has seen other values, and who knows the algorithm and the time, cannot compute this one. This is a security property against an adversary. - **Uniqueness**: this value has not been used before in the same context. This is a correctness property against *yourself*; an honest bug produces the collision just as easily as an attacker does. They are independent. A counter is perfectly unique and perfectly predictable. A random 8-bit value is unpredictable-ish and frequently repeats. ## Walking the consumers **Secret keys.** Requirement: unpredictability at full length. A key is only as strong as the entropy behind it, so a 256-bit key generated from a 32-bit seed is a 32-bit key wearing a costume. There is no uniqueness requirement per se — two independently generated keys colliding is a non-event at realistic sizes — but there is a *full-entropy* requirement, which is stricter than "looks random." **Bearer values: session identifiers, password-reset and invite tokens, API keys, CSRF tokens, one-time links.** Requirement: unpredictability, plus enough length that online guessing is hopeless even at attacker request rates. Uniqueness comes free once the length is right, but it is worth noticing that uniqueness alone would be satisfied by a sequential id — and a sequential session id is an enumeration disaster. This is the class where the wrong choice is most common, because the value is not called "a key" and nobody thinks of it as cryptographic material. **Nonces in counter-style encryption.** The contract these modes state is *never reuse a nonce with the same key*. That is uniqueness, and a monotonically increasing counter per key satisfies it deterministically. Randomly chosen nonces satisfy it only probabilistically, and the birthday bound means the collision probability grows with the square of the message count — which is why short random nonces are a scaling hazard and long ones are not. Unpredictability is not part of that contract at all. (What exactly the mode loses on reuse belongs with the discussion of cipher modes; the point here is that the requirement is uniqueness, and randomness is the weaker way to buy it.) **Chaining-mode IVs.** Some modes require the IV to be *unpredictable in advance*, not merely fresh, because an attacker who can predict the next IV and choose the next plaintext can test guesses about earlier plaintext. So here randomness genuinely is the requirement, and a counter is unsafe. The lesson is that "IV" and "nonce" are not interchangeable words: the mode defines the contract, and you read it rather than assuming. **Password salts.** Requirement: unique per stored credential. Salts are stored in the clear next to the hash — their purpose is to make precomputation useless and to stop one cracking effort from covering many accounts. They do not need to be secret and they do not need to be unpredictable; a per-record unique value would suffice in principle. Random is simply the easiest way to get uniqueness without coordination. A single global salt, or a salt derived from the username, silently loses the shared-work protection while everything still authenticates fine. **Non-security uses.** Retry jitter, sampling, load-balancer selection, test fixtures: no security property required, so an ordinary generator is fine and faster. The exception worth naming is anything with money or fairness attached — lotteries, shuffles in a game with stakes, giveaway draws — where "fair" quietly means "unpredictable to the participants," and the ordinary generator is a real vulnerability. ## The failure mode all of these share Every mistake in this list is silent. A reused nonce encrypts and decrypts. A shared salt hashes and verifies. A predictable token authenticates. There is no exception, no failed test, no log line. That is what makes the property-naming discipline worth the effort: it is applied at design time because there is no runtime signal afterwards. ## How to answer in an interview Say the sentence "randomness is not the requirement, it is one way of meeting a requirement," then classify: keys and bearer tokens need unpredictability; nonces need uniqueness and a counter is the better instrument; salts need uniqueness and are not secret; certain IVs need unpredictability because of a chosen-plaintext argument. Finish by noting that all of these fail silently, so the choice cannot be validated after the fact.

  • If a counter is a strictly better way to guarantee nonce uniqueness, why do implementations so often use random nonces anyway?
    Because counters need state that survives restarts and is not shared across concurrent writers or replicas — and a duplicated counter after a rollback, a clone, or a fork is worse than a random draw. Random nonces trade a deterministic guarantee for a stateless one whose failure probability you can compute from the nonce length and the message count. The right answer depends on whether you can genuinely own the counter.
  • A colleague derives password salts by hashing the username. What is lost, given that salts are public anyway?
    Uniqueness across systems, not secrecy. Because the salt is now a predictable function of a public identifier, an attacker can precompute tables for common usernames ahead of stealing the database, and the same precomputation is reusable against every deployment using the same scheme. A per-record random salt makes precomputation useless and forces the work to start after the breach.

saying these in an interview costs you the question

  • Treating "nonce" and "IV" as synonyms with the same requirements.
  • "The salt must be kept secret" — salts are stored in the clear; secret values used the same way are a different construct.
  • Assuming randomly chosen nonces are safe at any length, ignoring the birthday bound on collisions.
  • Using a sequential or timestamp-derived identifier for a session or reset token because "it is unique."
  • Believing a wrong choice will surface in testing — every failure in this family is silent.

context