Articles

What Is a Replay Attack?

A replay attack resends a captured, valid message to trick a system into repeating an action — and why timestamps, nonces, and signatures stop it.

Chisato Chisato · · 4 min read
A digital padlock with light trails

A replay attack is when an attacker captures a legitimate, valid message — a login request, a payment authorization, an API call — and resends it later to trick the receiving system into repeating the action, without ever needing to break the encryption or forge a signature. The message is genuine; it’s just being used at the wrong time, by someone who isn’t the original sender.

This is what makes replay attacks distinct from most other attacks in this space: they don’t require cracking anything. A perfectly valid, correctly signed request is the entire weapon.

Why a valid message can still be dangerous

Consider a request that authorizes a $50 transfer, signed with the user’s private key and sent over TLS. The encryption protects the message from being read or altered in transit, and the signature proves it really came from the user. Neither of those properties says anything about when the message is valid or how many times it can be used. If an attacker on the network captures that exact request — even encrypted, just by recording the ciphertext — and resends the identical bytes later, a server that only checks “is this signature valid?” will happily authorize a second transfer.

This is fundamentally different from a man-in-the-middle attack, where the attacker actively intercepts and alters traffic in real time. A replay attack can be entirely passive at capture time — just record traffic — and the “attack” itself happens later, by rebroadcasting what was recorded.

Where replay attacks actually show up

  • Authentication tokens. A captured session token or one-time password, resent before it expires, can log an attacker in as the original user.
  • Payment and transaction APIs. A captured “transfer funds” or “place order” request, resent, repeats the transaction.
  • Wireless protocols. Captured key-fob signals (garage doors, car locks) are a classic real-world example — the signal itself is valid, it’s just being replayed by someone who isn’t holding the fob.
  • Network authentication handshakes. Older protocols that didn’t account for replay could have a captured handshake message resent to re-establish a session the attacker shouldn’t have.

The defenses: make replaying impossible, not just detectable

Timestamps. Include the time the message was created and reject anything outside a short acceptable window (say, 30 seconds to a few minutes to allow for clock drift). A replayed message sent an hour later gets rejected outright.

Nonces. A nonce (“number used once”) is a unique value included in the request that the server tracks and refuses to accept twice. Even a replay attempted within the timestamp’s valid window fails, because the server has already seen and consumed that specific nonce. This is the same principle behind why a JWT’s jti claim exists — a unique token identifier a server can check against a used-token list.

Sequence numbers. Instead of a random nonce, some protocols use a strictly increasing counter per session; the server rejects any message with a sequence number it’s already seen or that goes backward.

Sequence numbers and nonces solve the same problem differently: a sequence number is compact and cheap to check (just compare against the last seen value), but it requires both sides to agree on ordering and can be disrupted if messages arrive out of order over an unreliable network. A random nonce doesn’t depend on ordering at all, but the server has to remember every nonce it’s seen within the valid time window, which costs more storage as traffic grows. Systems that need strict ordering anyway — like a session with sequential requests — tend to prefer sequence numbers; systems with independent, unordered requests tend to prefer nonces.

Challenge-response. The server sends a fresh, random challenge value that the client must sign or incorporate into its response. Because the challenge is different every time, a captured response from a prior exchange is worthless against a new challenge. This is part of why PKCE in OAuth exists — a fresh, per-request code verifier means a captured authorization code from one exchange can’t be replayed in another.

HMACs over the whole message including a nonce/timestamp. An HMAC proves the message wasn’t tampered with, but it doesn’t prevent replay by itself — the nonce or timestamp inside the signed payload is what stops the replay, and the HMAC is what makes tampering with that nonce or timestamp detectable.

Signatures alone don’t stop replay

It’s worth being explicit about a common misconception: a valid digital signature proves the message is authentic and unaltered — it does not prove the message is fresh. Signing algorithms have no concept of time or “has this been used before.” That’s entirely the job of whatever the signed payload contains — a timestamp, a nonce, a sequence number — plus server-side logic that actually checks and enforces those fields. A system that signs requests but never checks for reuse is still replayable.

A minimal example

A request body like this is replay-resistant, assuming the server enforces both fields:

{
  "action": "transfer",
  "amount": 50,
  "timestamp": 1732550400,
  "nonce": "f3a1-92be-77dd",
  "signature": "..."
}

The server rejects the request if timestamp is outside the acceptable window, or if nonce has already been seen for this account. Either check alone helps; both together close the gap almost entirely — the timestamp bounds how long a nonce needs to be remembered, and the nonce closes the window the timestamp leaves open.

The takeaway

A replay attack doesn’t forge anything — it captures a genuinely valid message and resends it later to repeat an action the attacker shouldn’t be able to trigger. Encryption and signatures alone don’t stop it, because neither says anything about timing or reuse. The actual defense is making messages single-use and time-bound: a timestamp to reject stale requests, a nonce or sequence number to reject duplicates, and server-side enforcement that actually checks both before honoring the request.

Chisato Chisato · · 4 min read

What Is mTLS? Mutual TLS Authentication Explained

mTLS is TLS where both client and server present certificates, so each side cryptographically proves its identity before any data is exchanged.

#Security #Networking #Authentication
Chisato Chisato · · 4 min read

OCSP vs CRL: How Certificate Revocation Works

OCSP and CRL are the two mechanisms browsers use to check if a TLS certificate has been revoked before its expiry date. Here's how each works.

#Security #Cryptography #Networking