noncechalant
stream cipher nonce reuse attack tool
When two ciphertexts are encrypted with the same key and nonce/IV, the keystream is identical. XORing the ciphertexts cancels it:
ct_a XOR ct_b = pt_a XOR pt_b
With any known text from one plaintext, the other is recovered. noncechalant makes this interactive, automated, or one-shot.
One-shot: you have the full plaintext of A python3 noncechalant.py a.bin b.bin --known-a plain_a.txt --side-by-side
Interactive: start with a short crib and extend byte by byte python3 noncechalant.py a.bin b.bin --crib "known text" --charset structured
Skip past shared header bytes (XOR=0, unresolvable) python3 noncechalant.py a.bin b.bin --crib "known text" --skip 107
Crib belongs to B, not A python3 noncechalant.py a.bin b.bin --crib "known text" --crib-side b --skip 107
Beam search: automated recovery for natural language plaintexts python3 noncechalant.py a.bin b.bin --crib "known text" --beam 50 --beam-top 5
Beam with wordlist for better scoring
python3 noncechalant.py a.bin b.bin --crib "known text" --beam 50
--wordlist /usr/share/dict/words
Resume an interrupted interactive session python3 noncechalant.py a.bin b.bin --session mysession.json --resume
gcm AES-GCM nonce(12) + ct + tag(16) [default]
chacha20 ChaCha20 nonce(12) + ct
chacha20poly ChaCha20-Poly1305 nonce(12) + ct + tag(16)
ctr AES-CTR nonce(8) + ct
cbc AES-CBC iv(16) + ct
ofb AES-OFB iv(16) + ct
salsa20 Salsa20 nonce(8) + ct
rc4 RC4 ct only (no nonce/tag)
raw custom use --ct-offset and --tag-size
printable All printable ASCII (default)
structured Letters, digits, common punctuation, good for reports/configs
alphanumeric Letters, digits, whitespace only
hex Hex digits and whitespace
binary All 256 bytes (no constraint)
At each ambiguous position the tool shows:
- Word candidates from your wordlist (A->B and B->A)
- Mid-word completions from your wordlist
- Char candidates filtered and sorted by context heuristics
Input at the prompt:
WORD Enter a word or phrase for side A (applied all at once)
b:WORD Enter text for side B; A is derived automatically
\x0a Hex escape, enter a specific byte (e.g. newline)
rewind N Back up N characters (default 1) to correct drift
skip Stop and output what was recovered so far
Session save/resume:
--session FILE Auto-saves after every manual input
--resume Load and continue from the saved session
Automated branch-and-bound over all valid charset pairs. Scores branches using character frequency, English bigrams, and token-level wordlist bonuses/penalties at whitespace boundaries.
Best for:
- Natural language plaintexts (messages, descriptions)
- Short unknown sections (under ~100 bytes)
- Any case where words dominate over specific numeric values
Not suited for:
- Structured documents with unpredictable values (timestamps, measurements, IDs), use --known-a for those
Flags: --beam N Beam width (try 30-100) --beam-top N How many top results to display (default 5) --wordlist F Wordlist file for token scoring (recommended: /usr/share/dict/words, not included)
You have full plaintext of one side --known-a plain.txt Natural language, both sides unknown --beam 50 --wordlist words.txt Structured doc, long shared header --skip N --crib "known text" Structured doc, partial known-A Interactive + long --crib Both sides fully unknown, short --beam 30 (may need guidance) RC4 or raw keystream --format rc4 / --format raw
--crib TEXT Known plaintext seed (default: empty) --crib-side a|b Which side the crib belongs to (default: a) --skip N Byte offset where crib starts (default: 0) --format FMT File format (see SUPPORTED FORMATS, default: gcm) --ct-offset N Ciphertext start byte (raw format only) --tag-size N Tag bytes to strip from end (raw format only) --charset CS Character set constraint (see CHARACTER SETS) --known-a FILE Full plaintext of A, one-shot recovery of B --wordlist FILE Wordlist for suggestions and beam scoring --beam N Beam search width (0 = interactive, default) --beam-top N Results to show in beam mode (default 5) --session FILE Session save/resume file path --resume Resume from saved session file --out-a FILE Output file for recovered A (default: recovered_a.txt) --out-b FILE Output file for recovered B (default: recovered_b.txt) --side-by-side Display both plaintexts in columns --diff Show only lines where A and B differ --no-color Disable ANSI color output --quiet Non-interactive; stop at first ambiguity
- Beam mode cannot recover specific numeric values (timestamps, packet counts, percentages) from frequency scoring alone. These positions are neutral; recovery requires known-A or interactive guidance.
- CBC mode with different IVs: XOR attack still works but reveals XOR of plaintexts only (not full recovery without one known side).
- GCM authentication tags are not verified (key not known). This does not affect plaintext recovery.
- Session files store raw recovered bytes; keep them private.