
A vulnerable implementation of the Kyber KEM decapsulation leaks secret key bits through timing differences in the ciphertext rejection step, enabling full key recovery.
Severity: Critical (Private Key Compromise)
// kyber_vuln_decaps.c - Simulated vulnerable Kyber decapsulation
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
// Secret key (simplified, 16 bytes for demo)
static uint8_t secret_key[16] = {
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88
};
// Vulnerable decapsulation: processes ciphertext and returns shared secret
// but timing leaks bit-by-bit comparison of a re-encrypted value.
int vulnerable_decaps(uint8_t *ct, uint8_t *shared_secret_out) {
// Simulate re-encryption: compare ct with a computed value byte by byte
uint8_t re_enc[16];
for (int i = 0; i < 16; i++) {
re_enc[i] = secret_key[i] ^ 0x55; // dummy computation
}
// Timing leak: early exit on first mismatch
for (int i = 0; i < 16; i++) {
if (ct[i] != re_enc[i]) {
return -1; // rejection, faster when mismatch early
}
}
memcpy(shared_secret_out, secret_key, 16);
return 0;
}
int main() {
// simulate receiving a ciphertext (hardcoded for demo)
uint8_t ct[16] = {0}; // attacker will probe
uint8_t shared[16];
int res = vulnerable_decaps(ct, shared);
// Timing measured externally
return 0;
}
An implementation of the Kyber post‑quantum KEM fails to use constant‑time comparison during decapsulation. By measuring execution time of rejected ciphertexts, an attacker can iteratively recover the full private key.
gcc -shared -o kyber_vuln.so -fPIC kyber_vuln_decaps.c
python timing_attack.py