keystream

package
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 14, 2026 License: Apache-2.0 Imports: 3 Imported by: 0

Documentation

Overview

Package keystream implements keystream-reuse / many-time-pad analysis — the real-world break against additive stream ciphers (P25 DES-OFB and ADP/RC4, TETRA AIE) when a transmitter reuses an initialisation vector. Under OFB and raw stream ciphers the keystream is a deterministic function of (key, IV); two frames sent under the same key and the same IV therefore share an identical keystream, and XORing their ciphertexts cancels it:

c1 ^ c2 = (p1 ^ ks) ^ (p2 ^ ks) = p1 ^ p2

leaving a classic running-key system that crib-dragging and a language model can peel apart — no key recovery required. For P25 the IV is the 72-bit Message Indicator the decoder already extracts, so this is the bridge from "encrypted, opaque" to "recoverable" whenever a radio's MI repeats.

This package only exploits operator misuse (IV reuse) and known plaintext; it does not attack the cipher's key, in keeping with the toolkit's scope.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func XOR

func XOR(a, b []byte) []byte

XOR returns a^b over the common prefix (min length). It is the additive stream-cipher primitive: keystream = pt^ct, and ct1^ct2 = pt1^pt2.

Types

type Decoded

type Decoded struct {
	Label     string
	Plaintext []byte
}

Decoded is one frame recovered by RecoverWithKnown.

func RecoverWithKnown

func RecoverWithKnown(group ReuseGroup, knownLabel string, knownPT []byte) (ks []byte, out []Decoded, ok bool)

RecoverWithKnown turns one known plaintext within a reuse group into the group's keystream (ks = knownPT ^ knownCT) and uses it to decrypt every other frame in the group. This is the decisive step once any single frame's content is known (a standard tone, a known data payload, a confirmed transcript). It returns the recovered keystream and the decrypted frames.

type DragHit

type DragHit struct {
	CribLabel    string
	PartnerLabel string
	Offset       int
	Revealed     []byte
	Score        float64
}

DragHit is one crib-drag placement: positioning crib at Offset in one ciphertext reveals Revealed in the partner, scored by a language model.

func CribDragGroup

func CribDragGroup(group ReuseGroup, crib []byte, topN int) []DragHit

CribDragGroup slides crib across every ordered ciphertext pair in the group (c_i ^ c_j ^ crib) and returns the placements whose revealed partner bytes are fully printable, ranked by English trigram score — the highest are the likely true positions. With the right crib this peels plaintext out of a reuse group with no key and no known plaintext.

type Frame

type Frame struct {
	Label string
	IV    []byte
	CT    []byte
	AlgID uint8
	KeyID uint16
}

Frame is one captured encrypted unit: an IV (e.g. a P25 Message Indicator) and the ciphertext under that IV. Label identifies the source (call id, timestamp) for reporting. AlgID/KeyID are the optional algorithm and key identifiers from the capture (0 when unknown), used by the assessment harness to select the right cipher for a decryption attempt.

type ReuseGroup

type ReuseGroup struct {
	IV     []byte
	Frames []Frame
}

ReuseGroup is a set of frames that share an identical IV and therefore an identical keystream.

func FindReuse

func FindReuse(frames []Frame) []ReuseGroup

FindReuse groups frames sharing an identical IV, returning only groups with at least two frames (the exploitable ones), largest group first. Frames with an empty IV are ignored — without an IV there is nothing to collide.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL