Also known as: Motorola alias cipher, per-byte alias cipher
The Motorola talker-alias cipher is the proprietary per-byte obfuscation Motorola applies to a radio’s talker alias — the human-readable display name — before it is fragmented across the air.1 It is not encryption for confidentiality in the AES sense; it is a lightweight, undocumented scrambling of the alias string that a receiver must reverse to read the name. Its structure is a length-seeded 16-bit additive accumulator, a 256-byte substitution table, and an odd-multiplier (modular-inverse-mod-256) step, with the decoded bytes read as UTF-16 BE.
This cipher was recovered by clean-room reverse engineering and is verified. It was
reconstructed from black-box (input → output) observations of an existing decoder driven as an
opaque oracle — no third-party source or table was read or copied — and it decodes a real
over-the-air capture (RID 200062 → “CRIO 0062”) with a valid CRC. GopherTrunk decodes it by
default (CipherVerified = true). For the full recovery method, reproducible validation, and
the clean-room provenance/licensing record, see
the clean-room provenance document.
The per-byte transform
The decode-side transform lives in internal/radio/p25/motorola/alias.go. There is no vendor
spec — the algorithm below was recovered from behaviour — so it is worth showing:
// W seeded from the character count n = len(encoded)/2; LUT is a 256-byte table.
n := len(encoded) / 2
w := uint16(0xC433 + 586*(n-1)) // length seed (586 = 2*293)
for i := 0; i < 2*n; i++ {
// per-byte substitution: odd-multiplier × (table lookup − accumulator high byte)
out[i] = motorolaAliasInvOdd[byte(w)|1] * (motorolaAliasLUT[encoded[i]] - byte(w>>8))
w += uint16(293 * (int(encoded[i]) + 1)) // additive accumulator update
}
// pack pairs into UTF-16BE chars; force the high byte to 0xFF when the low byte is >= 0x80.
motorolaAliasInvOdd[(W&0xFF)|1] is the multiplicative inverse of the accumulator’s low byte
(forced odd) modulo 256, and the subtraction mixes in the accumulator’s high byte W>>8. The
accumulator update is additive (W += 293·(byte+1)) — an earlier inferred multiplicative
form (accum×293+0x72E9) was wrong and decoded nothing; the oracle recovery corrected it. The
decoded byte stream is read as UTF-16 BE and rendered to printable ASCII.
Verification status
Both the SUID framing (WACN / System / Radio ID prefix) and the
cipher itself are verified. The cipher was recovered by clean-room reverse engineering —
reconstructed from ~22,000 black-box (input → output) observations of an existing decoder
driven as an opaque oracle — and it reproduces that oracle byte-for-byte on a 300-row held-out
set it never trained on (1242/1242 characters). Independently, it decodes a real
over-the-air capture (RID 200062) to “CRIO 0062” — clean ASCII whose “0062” is the tail of
the radio’s own ID — with a CRC-16/GSM that matches the on-air bytes (0x6A96). The earlier
worry that the one #376 sample was “underdetermined” was a framing artifact: the cipher length
must be taken from the self-delimiting CRC boundary (stripping the trailing FACCH pad), after
which it decodes cleanly.
The decode is gated behind the CipherVerified constant, now true, standing on a
committed regression fixture (the held-out oracle vectors). While true, a clean-ASCII decode is
reported reliable and the name surfaces; a garbled decode is still flagged unreliable. See the
clean-room provenance record
for the method and reproducible validation.
Licensing
A working implementation also exists in SDRTrunk (GPLv3); GopherTrunk is Apache-2.0, so that source and table were not ported. The cipher was instead recovered by clean-room reverse engineering: an existing decoder was driven as an opaque black-box oracle — its public decode accessor only, with no source, table, or algorithm read or copied — and the cipher’s structure and 256-byte table were reconstructed as functional facts from the observed input/output behaviour, then re-implemented independently in Go. The GPL-linked measurement instruments were quarantined and never committed. The full provenance — the exact boundary of what was and was not read, and the reproducible validation — is documented in the clean-room provenance record.
Sources
-
Project 25 — Wikipedia, on the P25 standard. The cipher is a proprietary Motorola extension with no vendor specification; it was recovered by clean-room reverse engineering and verified against real over-the-air data per GopherTrunk issue #773. ↩