The Identity Block
Thirty-two bytes at the head of a request body that say who is calling. This is not a header, and it is not universal — the QMail command family uses it, and other command families do not.
A note on naming
This used to be called the "48-byte modern authenticated preamble"
That name caused more confusion than any other term in this documentation, in four separate ways:
- It is not a preamble. It does not precede the body; it is the beginning of the body, inside the encryption.
- "48 bytes" collided with an unrelated 48-byte structure elsewhere in the protocol, and both were described on the same documentation page.
- "Modern" meant nothing. It had been applied to three different generations of design.
- "Authenticated" was not always true. Whether the identity is actually checked depends on the command — see below.
The 48 in the old name came from counting the 16-byte challenge along with the 32-byte identity structure. The challenge belongs to the protocol layer and is present on every request regardless of whether an identity follows it, so this page counts the identity block as 32 bytes and treats the challenge separately.
Layout
Body offsets 0–47 of a decrypted QMail request. The challenge is shown for orientation; the identity block itself is bytes 16–47.
| Body bytes | Size | Field | Meaning |
|---|---|---|---|
| 0–15 | 16 | Challenge | 12 random bytes plus their CRC32. Protocol layer, not part of the identity. Present on every request. |
| 16–23 | 8 | Session ID | Reserved. Always zero today, and no server reads it. See below. |
| 24–25 | 2 | Coin type | CloudCoin is 0x0006. |
| 26 | 1 | Denomination | Denomination of the identity coin. |
| 27–30 | 4 | Serial number | Serial number of the identity coin, big-endian. |
| 31 | 1 | Reserved | Formerly a device ID. No longer used; the server ignores it. |
| 32–47 | 16 | Authenticity Number | The identity coin's AN on the RAIDA being addressed. |
The identity coin is not the key coin
The coin named here — the one whose AN proves who you are — is generally a different coin from the one named in the request header, whose AN encrypts the packet. Two coins, two roles, two places in the request. Confusing them produces requests that decrypt correctly and then fail authorisation, or vice versa.
How the server verifies it — and when it does not
Where the identity is checked, the server looks up the coin by denomination and serial number in its own database and compares the stored AN against the one in the block. A mismatch returns ERROR_INVALID_AN (200); an unknown coin returns ERROR_INVALID_SN_OR_DENOMINATION (40).
But this is a per-command behaviour, not a property of the structure:
| Command | Identity AN verified? |
|---|---|
| 70 upload | Yes |
| 71 tell | Yes — and the sender named inside the payload must match the verified identity |
| 72 ping, 73 peek | Yes |
| 85 subscribe | Yes — the identity coin is the vendor |
| device link commands | Yes — each device authenticates with its own coin |
| 74 download | No. See below. |
Download does not authenticate its identity coin
The download handler never looks the coin up and never compares the AN. The AN in the block is still consumed — it is used as key material by the encryption layer — but no authorisation decision is made from it. Access is gated by an ACL sidecar instead.
This has a practical diagnostic consequence. If a client builds a download request with a zero AN in the identity block — a common bug when an encryption-state structure is aliased unsafely — the server cannot derive the right key, fails to decrypt the body, never reaches the handler, and returns ERROR_INVALID_ENCRYPTION (34). The error points at encryption, but the cause is the identity block.
Two ways to count the offsets
Server and client code count this structure from different origins, which is worth knowing before you compare them:
| Counts from | Calls it | Session ID at | |
|---|---|---|---|
| Server | the start of the decrypted body, challenge included | 48 bytes | offset 16 |
| Client | the start of the identity structure it writes | 32 bytes | offset 0 |
The same bytes, sixteen apart. The client's packet builder prepends the challenge separately, so the client library never sees the challenge as part of "the preamble" while the server always does. When reading either codebase, check which origin is in use before trusting an offset.
DRD does not use this layout
There are currently two identity conventions in the protocol
This page documents the QMail identity block. The DRD command family (group 16) does something different: it places the caller's denomination, serial number and AN inline at the start of its command payload, immediately after the challenge, with no session field, no coin type and no reserved byte.
The verification logic is equivalent — DRD looks the coin up and compares the AN, just as QMail does — but the fields sit at different offsets and are reached by different code. A client cannot reuse its QMail identity builder for DRD.
DRD is pre-production and this is expected to change. Converging DRD onto the shared identity block is under consideration; the window for doing that without a wire break closes when DRD ships. Until it is decided, treat DRD's identity layout as documented on the DRD command pages, not here.
Other command families — authentication, locker, change, RKE — place their coin data directly in their command payloads in whatever shape the command needs. They do not have an identity block at all. Do not assume this structure exists in a request unless the command's own page says so.
The reserved session field
Bytes 16–23 are named for a session ID, are present in every deployed client and server, and are zero in every request on the wire today. No server reads them.
They exist because a RAIDA authenticates callers by coin ownership, while a non-RAIDA service — a Content Server, or a QMail server running off-RAIDA — cannot: it has no coin database to check an AN against. Such a service authenticates a caller once, then issues a session. The field was reserved so that a session could eventually be presented in the same slot a coin identity occupies.
Status: reserved, not implemented
No mechanism currently assigns, transmits or validates a value in this field. A client MUST continue to send zeros. Anything that reads a nonzero value here today is reading a field no specification has yet defined.
Note that Content Server traffic solves the same problem at a different layer: encryption type 9 carries a session handle in the request header, and the possession of the session key is itself the authentication — no coin authenticity numbers appear on that wire at all. Whether RAIDA-hosted services should also accept session-authenticated callers, and if so through which of these two mechanisms, is an open design question.