Replay Protection
Replay Protection
The sliding window algorithm
Replay attacks occur when an attacker captures a valid encrypted packet on the wire and retransmits it later. Since the packet has a valid ciphertext and authentication tag, a naive receiver would decrypt and process it twice.
The 1024-bit Sliding Window
KSP implements a sliding window algorithm based on monotonically increasing sequence numbers. Unlike a strict increment counter which rejects out-of-order packets (breaking on lossy networks), the sliding window allows packet reordering while strictly rejecting duplicates.
Sliding Window State:
- highest_seq: The largest sequence number validated so far.
- bitmap: A 1024-bit bitmask representing [highest_seq - 1023, highest_seq].
Rust Implementation Logic
pub struct ReplayWindow {
highest_seq: u64,
bitmap: [u64; 16], // 16 * 64 bits = 1024 bits
}
impl ReplayWindow {
pub fn check_and_update(&mut self, seq: u64) -> bool {
if seq > self.highest_seq {
// Packets ahead of current window
let diff = seq - self.highest_seq;
if diff >= 1024 {
self.bitmap = [0; 16];
} else {
self.shift_bitmap(diff);
}
self.highest_seq = seq;
self.set_bit(0); // Bit 0 represents highest_seq
return true;
}
let age = self.highest_seq - seq;
if age >= 1024 {
// Packet is too old, outside sliding window
return false;
}
if self.is_bit_set(age) {
// Already processed (replay attack)
return false;
}
self.set_bit(age);
true
}
}Security Warning
Replay-rejected frames MUST be discarded silentlywithout returning an error code. Generating error packets for invalid sequences allows side-channel analysis, helping attackers map the receiver's current sliding window.