Also known as: ES, encryption sync, message indicator
The P25 Encryption Sync (ES) is the field an encrypted P25 voice call publishes so a receiver holding the key can decrypt it — and so any monitor can identify the encryption.1 It carries three things: the Message Indicator (MI), a 72-bit per-call cryptographic sync vector that seeds the keystream generator (the initialization vector); the ALGID (algorithm ID) naming the cipher; and the KID (key ID) selecting which key in the radio’s keyset the call uses. Like SDRTrunk, GopherTrunk reads these to label a call as encrypted — algorithm and key — without decrypting it.
Where it rides and how it is protected
The ES travels in an LDU2 — the second of the two voice frames a P25 call alternates —
using the same six 40-bit slots an LDU1 uses for its
Link Control word. Those slots carry an inner shortened
Hamming(10,6,3) code across the 24 codewords, exactly as Link Control does. Above that
sits an outer Reed-Solomon RS(24,16,9) code (t = 4
symbols), which GopherTrunk’s ParseEncryptionSync runs after the Hamming layer to correct
the residual symbol errors that would otherwise smear the algorithm ID under marginal SNR.
If more than four symbol errors survive the inner layer, the RS code fails and the parser
returns ErrEncryptionSyncUncorrectable — the decoded algorithm and key are then
low-confidence and are not surfaced as a real encryption change.
The fields
internal/radio/p25/phase1/encryption_sync.go decodes the 12-octet ES content:
| Octets | Field | Meaning |
|---|---|---|
| 0–8 | Message Indicator | 72-bit per-call IV that seeds the keystream |
| 9 | Algorithm ID | cipher in use (0x80 = clear/unencrypted) |
| 10–11 | Key ID | which key in the keyset the call uses |
A monitor uses the MI even when it cannot decrypt: the MI advances predictably across the
call, so it also serves as a sanity check that the crypto framing is being tracked correctly.
Because a bit-error in a traffic-channel ES smears the algorithm ID roughly uniformly across
0x00–0xFF, GopherTrunk gates surfacing on the ALGID being a registered value — an
out-of-set ALGID is provably a mis-decode and is dropped rather than shown as a fabricated
algorithm.
Relevance to SDR
Reading the ES is how GopherTrunk answers the operator’s first question about an encrypted call — what algorithm and key? — which drives call-log fields, the encryption indicator in the UI, and any decrypt attempt in the crypto lab. The ALGID tells whether the traffic is clear or protected; the MI feeds the keystream generator if a key is available; and the KID lets an operator correlate calls that share a key, which is exactly the metadata OTAR rekeying changes over time. The two-layer FEC is what makes this metadata trustworthy off-air, so GopherTrunk decodes both layers before believing an ALGID.
Sources
-
Project 25 — Wikipedia, on the P25 standard and its encryption services. ES layout and FEC follow TIA-102.AABF/AACE as the project’s working model. ↩