Safeguard
Application Security•

CWE-323 Reusing a Nonce, Key Pair in Encryption: What Goes Wrong

A nonce is meant to be used once. CWE-323 covers code that reuses a nonce with the same key, opening the door to replay and tampering.

Safeguard Security Team
3 min read

CWE-323, Reusing a Nonce, Key Pair in Encryption, is built on a simple rule from MITRE: nonces should be used for the present occasion and only once. Break the rule and the guarantees of the scheme can fail.

Anyone writing code that calls encryption primitives directly is exposed, especially with modes where the nonce is a required input.

How it happens

The nonce is a value supplied alongside the key. If the same pair appears twice, an attacker who sees both messages can learn things they should not, or replay old messages as new ones. Typical causes are a constant nonce in the source, a counter that resets on restart, or a state object that is cloned and resets its generator.

# Vulnerable: fixed nonce reused with the same key
nonce = b"\x00" * 12
ct = AESGCM(key).encrypt(nonce, message, None)

Observed examples show how this plays out in current software. CVE-2024-36289 is a social networking app that reused a nonce and key pair, allowing adversary in the middle attackers to manipulate direct messages. CVE-2024-21530 is a Rust package that reuses a nonce and key pair when an object is cloned, which resets the random number generation.

What an attacker gains

MITRE lists access control bypass and the possibility of gaining privileges or assuming identity. Potentially this is a replay attack, in which an attacker sends the same data twice and the system accepts it.

How to find it

Static analysis can flag some cases, such as constant nonce arguments. For libraries, read how state is copied: anything that duplicates a generator should be treated with suspicion. Tests that encrypt two messages and compare the nonces are cheap and effective.

How to fix it

  1. Refuse to reuse nonce values. Track what has been used, or make reuse structurally impossible.
  2. Use techniques such as incrementing counters, time based values or challenge response to assure uniqueness.
  3. Generate a fresh random nonce per message, drawn from a cryptographically secure source, where the scheme allows it.
# Fixed: new random nonce for every message, sent with the ciphertext
nonce = os.urandom(12)
ct = AESGCM(key).encrypt(nonce, message, None)
  1. Rotate keys on a schedule so a counter cannot wrap within one key's life.

Quick check

Can I store the nonce next to the ciphertext?

Typically yes. Nonces generally need to be unique, not secret. Check the documentation of the scheme you use.

Why does cloning an object matter?

If the clone copies the generator state, both copies can emit the same values. That is the Rust package case above.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.