The most popular advice about initialization vectors is also the least complete: “Use a random IV.” That instruction points in the right direction, but it doesn't explain what the IV does, why AES-GCM treats reuse as a severe cryptographic failure, or why a production system can safely store the IV beside encrypted data.
If you've shipped encrypted features without auditing them, think of the IV as an input to encryption, not as another password. It normally travels with the ciphertext, stays visible to the server, and still needs strict uniqueness under the same key. The distinction matters in encrypted chat, file protection, and any browser-based system where the server should relay ciphertext without receiving the decryption key.
What an Initialization Vector Actually Does
An initialization vector, or IV, is a public input that makes encryption produce different output when the key and plaintext stay the same. Without that changing input, encrypting the same message with the same key could create the same ciphertext every time. An observer might not read the message, but they could identify repeated messages and infer patterns.
A useful analogy is a secure label placed into the encryption process. The label isn't secret, and it doesn't replace the key. It changes the starting state so the cipher doesn't produce a predictable result for repeated content.

The key distinction
The key protects confidentiality. The IV helps prevent repeated inputs from creating repeated ciphertext. If an attacker learns the IV, they haven't learned the key or the plaintext. They can use the IV as part of the public message envelope, but they still need to defeat the encryption key to recover protected content.
For AES-GCM, the IV influences the counter sequence used to generate the encryption keystream. A fresh IV therefore causes the same key to generate a different keystream for another encryption operation. The plaintext is combined with that keystream to create ciphertext that doesn't visibly repeat just because the message repeats.
Practical rule: Treat the IV as public, but treat its uniqueness as a security requirement.
This is similar to how developers separate public routing information from private credentials. A public channel name can identify where a request belongs, while the access key controls whether anyone can open it. If you're designing secure workflows beyond encryption, this guide for curated job seeking is a useful example of how a product can expose a clear user-facing process without confusing visibility with authorization.
The IV should usually be transmitted in the clear and stored beside the ciphertext and authentication tag. It shouldn't go into a secrets manager merely because it appears in an encryption record. Hiding it adds operational complexity without providing confidentiality. The security boundary is the key, while the IV's boundary is freshness and uniqueness.
The IV as a Number, Not a Secret
An IV is a sequence of bytes. In AES-GCM, the conventional reference is a 96-bit IV, which equals 12 bytes. Applications often serialize those bytes as Base64 inside a JSON envelope, but Base64 is only a transport representation. It doesn't make the IV secret, stronger, or longer in cryptographic terms.
The key is different. AES uses a key with a defined cryptographic size, commonly 128, 192, or 256 bits. A key selects the secret transformation. The IV selects the starting input for that transformation. A salt belongs to another layer, usually password-based key derivation, where it prevents the same password from producing the same derived key across separate contexts.
A nonce is related but broader. The word means a value intended for one-time use. Depending on the algorithm and mode, developers may use “nonce” and “IV” almost interchangeably, or they may use nonce to emphasize a counter-based uniqueness requirement. Code review should follow the actual mode's requirements instead of relying on labels.
Comparison of cryptographic inputs
| Field | Length, typical | Secret? | Purpose |
|---|---|---|---|
| IV | 96 bits, or 12 bytes, for AES-GCM | No | Changes the starting input and prevents repeated encryption patterns |
| Key | 128, 192, or 256 bits for AES | Yes | Controls the secret encryption and decryption transformation |
| Salt | Application and KDF dependent | No | Separates password-derived keys and prevents identical derivation contexts |
| Nonce | Mode dependent | No | A value designed for one-time use, often functioning as an IV or counter input |
AES-GCM can process IVs beyond the conventional size, but the 96-bit form is the preferred design target because it maps cleanly into GCM's internal initialization procedure. NIST's SP 800-38D guidance for GCM defines the mode and its IV processing rules. The practical audit conclusion is simple: if a library's AES-GCM API expects a 12-byte IV, pass exactly that format unless the library documentation and your security review justify another choice.
Don't confuse IV size with password strength. A longer IV doesn't compensate for a weak key, and a random-looking Base64 string doesn't prove that the underlying bytes were generated safely. Review the generation method, the scope of uniqueness, and the way the application handles process restarts.
How AES-GCM Uses the IV Internally
AES-GCM combines counter-mode encryption with authentication. It doesn't merely attach an IV to AES and call the result protected. The IV affects the counter stream and also participates in the authenticated computation.
A simplified flow looks like this:
- The caller supplies inputs. AES-GCM receives a key, an IV, plaintext, and optional additional authenticated data, or AAD. AAD might include protocol fields that should be authenticated but not encrypted.
- GCM builds its starting counter state. For the conventional 96-bit IV format, GCM constructs an internal value called
J0from the IV and a fixed suffix. Other IV lengths go through a hashing step to form the equivalent starting state. - AES generates keystream blocks. The key encrypts successive counter values derived from
J0. Those outputs form a keystream. - The plaintext becomes ciphertext. GCM XORs the keystream with the plaintext. The receiver can reverse that operation with the same key, IV, and counter sequence.
- GHASH authenticates the record. GCM processes AAD, ciphertext, padding, and length information through its polynomial hash over a 128-bit field.
- The tag is finalized. GCM combines the GHASH result with an AES-derived value tied to the starting counter state, producing the authentication tag.

The IV therefore affects both confidentiality and integrity. Changing it changes the counter-mode keystream and changes the authentication computation. Reusing it under the same key repeats both critical ingredients, which is why the failure is more serious than duplicated metadata.
For a browser implementation, the output should be treated as a structured record rather than one opaque string. Every encryption call should produce:
- Ciphertext, the encrypted application data.
- Authentication tag, the value the receiver verifies before accepting the plaintext.
- IV, the public input required to reproduce the GCM operation.
A practical encrypted-message walkthrough such as Ciphar's encrypted message example helps connect those abstract artifacts to an application payload. The wire format can vary, but the receiver must obtain the same IV and tag that the sender used.
This short visual explanation can also help when reviewing the sequence:
The receiver must verify the tag before releasing plaintext to the application. A successful decryption routine isn't just “AES returned bytes.” It means the key, IV, ciphertext, AAD, and tag formed a valid authenticated record.
Why IV Reuse in GCM Is Catastrophic
Suppose two plaintexts, P1 and P2, use the same AES-GCM key and the same IV. GCM generates the same keystream for both messages. The ciphertexts can be represented as:
C1 = P1 XOR S
C2 = P2 XOR S
An observer who XORs the ciphertexts gets:
C1 XOR C2 = P1 XOR P2
The shared keystream S cancels. The attacker still doesn't automatically receive both plaintexts in readable form, but the relationship between them leaks. Known or guessable portions of one message can expose corresponding portions of the other, and predictable message formats make the leakage more useful.
That is already a confidentiality failure. GCM adds a second failure because its authentication tag relies on a hash subkey and a polynomial calculation over the authenticated data.
The integrity failure
GCM derives a secret hash key from AES and uses GHASH to authenticate AAD and ciphertext. Repeated IV use gives an attacker related authentication outputs under the same starting conditions. With enough information, an attacker can derive constraints on the hidden hash calculation and construct ciphertext and tag combinations that pass verification.
The result isn't limited to “the two duplicated messages are weaker.” A successful nonce-reuse attack can undermine the authenticity of messages protected under that key. An attacker may be able to alter or forge records that the receiver accepts as valid, even without learning the AES key.
Reusing a GCM IV is not a cosmetic defect. It can expose relationships between plaintexts and compromise the mechanism that tells the receiver whether a message is authentic.
This is why “random” isn't the complete requirement. A random generator can produce a collision, while a counter can fail after a crash or state rollback. The implementation must establish a credible uniqueness guarantee for every encryption operation using a particular key, including operations performed by multiple browser tabs, workers, devices, or service instances.
If reuse is detected, don't continue using the affected key as though the problem were isolated. Stop accepting new records under that key, rotate the key where the protocol permits it, and investigate the scope of affected ciphertexts and tags.
How Production Systems Like Ciphar Handle IVs
A production message flow makes the public nature of an IV easier to understand. On the sender side, the application creates a fresh IV for the message, passes it to AES-256-GCM with the encryption key and plaintext, and receives ciphertext plus an authentication tag. The sender then packages those values into an outgoing payload.
The IV travels alongside the encrypted content. A relay can forward it, parse its length, and store it without gaining the ability to decrypt the message. Possessing the IV doesn't provide the key, and changing the IV causes tag verification to fail rather than revealing useful plaintext.

What belongs in the message envelope
A practical database record can keep the public and secret roles separate:
- Ciphertext, stored as opaque encrypted content.
- Authentication tag, needed for verification.
- IV, stored in the clear beside the encrypted content.
- Protocol context, such as an associated channel or record identifier, if the design authenticates it as AAD.
The server doesn't need to hash or encrypt the IV. It does need to preserve it exactly, return it with the matching ciphertext and tag, and avoid accidentally substituting one record's IV for another. Database indexing can identify the record, but indexing doesn't create replay protection by itself. The protocol must define whether an old authenticated record remains acceptable.
Ciphar's documented model uses browser-side AES-256-GCM so messages, files, replies, and edits are encrypted before they leave the device. Its relay stores opaque ciphertext with the values needed to transport and verify each encrypted record, while the decryption key remains outside the server. For a deeper explanation of the separate secret material involved, see how encryption keys work.
The audit question isn't “Can the database hide the IV?” Ask instead: Can every encryption operation produce a unique IV under its active key, and can every receiver bind the IV to the correct ciphertext and tag? That question catches more real failures than treating every field in an encryption envelope as a secret.
Three Sources of IVs and Their Tradeoffs
Random generation is the easiest design to deploy when a cryptographically secure random-number generator is available and the application can tolerate a probabilistic uniqueness argument. The application requests a fresh 96-bit value for each encryption operation, stores it with the record, and never tries to recreate it from the plaintext or key.
A counter provides a different guarantee. The sender can allocate a monotonically increasing value and combine it with an identifier for the sender or key domain. This can make uniqueness easier to reason about, but the state must survive crashes, restores, concurrent workers, and failover. A counter that rolls back can repeat an IV even though every individual process believes it behaved correctly.
HKDF-derived IVs fit protocols that already derive per-session material from a shared secret. The protocol can derive a session-specific base and then combine it with a per-message sequence value. HKDF itself doesn't make every message unique. The construction still needs message variation, state management, and clear rules for receiving messages out of order.
Comparison of IV sources
| Source | Uniqueness guarantee | Failure mode | Best use case |
|---|---|---|---|
| Random 96-bit IV | Probabilistic, dependent on a sound CSPRNG | Generator failure, faulty seeding, or an unlikely collision | Stateless or loosely coupled message producers |
| Deterministic counter | Strong when state is exclusive, persistent, and monotonic | Crash recovery, rollback, concurrency, or counter reuse | Stateful protocols with reliable sequence management |
| HKDF-derived IV | Depends on unique per-message inputs | Repeated sequence values, bad session separation, or lost state | Derived channels with an established key schedule |
The choice should follow the system's failure model. A browser can generate a random IV locally without asking the server for coordination. A multi-process service may prefer a coordinated counter or a construction that partitions the IV space among producers. A session protocol may derive values from a secret, but it still needs a message number or equivalent unique input.
Don't combine strategies casually. For example, hashing a key and a timestamp may look deterministic and unpredictable, yet it can repeat after clock adjustments or across processes. Document who owns uniqueness, what happens after restoration, and how the system detects a violation.
Developer Audit Checks for IV Correctness
Start at the encryption API. An AES-GCM call should receive an explicit IV, and the code should validate the expected format before encryption and decryption. For the conventional GCM design, that means checking for a 12-byte IV, rejecting malformed envelopes, and ensuring the authentication tag is verified before plaintext reaches application code.
Review the generator and its scope
Search the codebase for patterns that turn a supposedly unique value into a static one:
- Hardcoded values: Reject fixed IV constants, default byte arrays, and test fixtures that can reach production.
- Key-only derivation: Flag IVs computed solely from a key, because repeated messages under that key receive the same input.
- Clock shortcuts: Review timestamps, truncated timestamps, and timestamp values reduced to a small range.
- Cross-process reuse: Identify whether workers, tabs, devices, or restored snapshots can produce the same value under one key.
- State rollback: Test crash recovery, retries, queue replay, backups, and database restoration.
The storage review should be equally direct. The IV belongs beside its matching ciphertext and authentication tag, and the transport format should preserve those relationships. It doesn't belong in a key vault merely because the record is security-sensitive. Log systems should avoid logging plaintext or keys, but a carefully designed reuse detector can monitor IV fingerprints, message identifiers, or authenticated envelope relationships without exposing content.
Run the verification ritual
Use four tests against a real implementation:
- Generate: Encrypt repeated plaintexts and confirm each operation receives a fresh IV.
- Transmit: Serialize and deserialize the envelope without changing the IV bytes.
- Decrypt: Recover the original plaintext only when the key, IV, AAD, ciphertext, and tag all match.
- Reject: Modify the ciphertext, tag, IV, or authenticated context and confirm decryption fails before the application uses the result.
A focused review of AES-256 encryption in practice can help developers compare the algorithm choice with the surrounding key and envelope handling. Algorithm selection alone won't save a system that reuses nonces or skips tag verification.
Check browser workers and test environments separately. A correct main-thread implementation can still fail when a worker uses a copied counter, a retry repeats an entire encryption request, or a fixture supplies a constant IV. Treat uniqueness as an invariant that crosses process boundaries, not as a local property of one function.
Ciphar provides browser-based, zero-knowledge encrypted chat with client-side AES-256-GCM for short-lived messages, files, replies, edits, and voice frames. If you need to examine how public IVs, authentication tags, and client-held keys fit into an ephemeral conversation model, visit Ciphar.



