?>

High Security Request Headers

Encryption types 8 and 9. Both are AES-256-GCM with a 64-byte header. They differ in one thing only: where the key comes from, and therefore what kind of server they address.

Which one do I use?

The choice is made for you by what you are talking to, not by a security preference — the two types are equally strong.

 Type 8Type 9
Destinationa RAIDAa Content Server
Key located bytwo coin selectorsa 5-byte session handle
Key materialAN_A || AN_Bthe session key
Caller identified bycoin ownershipthe session
Command coveragethe RAIDA command seta narrower set — see below

Why type 9 serves fewer commands

A Content Server holds no coin database. Commands whose whole purpose is to prove or transfer coin ownership — detect, pown, healing, locker, change, shard conversion — have nothing to verify against there, so they are not part of the type 9 command set. This is a property of what a Content Server is, not a gap waiting to be filled.

Coin authenticity numbers never appear on the type 9 wire at all. Possession of the session key is the authentication.

What they share

Both use a 64-byte request header and return a 32-byte response header. Both authenticate the header as well as the body: the GCM tag covers header bytes 0–47 as additional authenticated data, so no byte of the header can be altered in flight without the tag failing.

PropertyType 8Type 9
CipherAES-256-GCMAES-256-GCM
Request AADheader bytes 0–47header bytes 0–47
Tagbytes 48–63, full 16bytes 48–63, full 16
Nonce12 bytes at 29–4012 bytes at 26–37
Body length at22–23, 16-bit22–25, 32-bit
Bytes 8–15reservedMUST be zero
Client echoforced zeroforced zero
Replay protectionnonea 64-bit counter

One command family cannot use these types

The QMail Object Transfer commands (6/76–84) require encryption type 1 and reject types 8 and 9 with ERROR_UNSUPPORTED_PROTOCOL (219).

The reason is a byte-layout collision, not a security decision: those commands carry a 32-bit body length in header bytes 10–13, which the High Security types use for other fields. See the Object Transfer framing for the details. Every other RAIDA command family accepts type 8.

The two are not layout-compatible

Both headers are 64 bytes, and it is tempting to treat them as one format with a different key selector. They are not. The body length, the nonce and the counter all sit at different offsets, so a parser written for one will mis-read the other. Branch on byte 16 before reading any other field.

Header Version 2 is the layout that finally puts type 8 and type 9 on the same offsets. It is a new value of byte 0, not a revision of these two maps.

Key selectors are readable, and that is deliberate

The bytes that identify the key — the coin selectors under type 8, the session handle under type 9 — travel in the clear. They have to: the receiver must read them to work out which key to decrypt with, so encrypting them would be circular.

They are not unprotected. Because they fall inside the authenticated header range, altering any of them invalidates the GCM tag and the request is rejected. A selector is a lookup key, never a secret; the security rests on possession of the key it points at.

Type 8 — AES-256-GCM, keyed by two coins

Type 8 is authenticated encryption: the header is not merely a container, it is cryptographically bound to the body. Tampering with any byte of the first 48 header bytes invalidates the request.

VR0SP1RI2SH3CG4CM5ID6PR8RS (Reserved)9EN=816DN A17SN A18BL22DN B24SN B25NO29NO (Nonce continues)32NO40RS (Reserved, MUST be zero)41AT (GCM Auth Tag)48AT (GCM Auth Tag continues)56
BytesFieldRequirement
0–15as type 1Routing, command, coin type, reserved.
16ENMUST be 0x08.
17DN ADenomination of key coin A.
18–21SN ASerial number of key coin A, big-endian.
22–23BLBody length, 16-bit big-endian, including the terminator. Minimum 18.
24DN BDenomination of key coin B.
25–28SN BSerial number of key coin B, big-endian.
29–40NO12-byte GCM nonce from a CSPRNG. The most significant bit of byte 29 MUST be 0 on requests.
41–47RSMUST be 0x00. These are inside the AAD, so they cannot be quietly repurposed later.
48–63ATThe full 16-byte GCM tag. Truncation is forbidden.

Key construction. For target RAIDA r, with AN_A and AN_B being the two key coins' authenticity numbers on that RAIDA:

K = AN_A || AN_B          (32 bytes, A first, order MUST NOT change)

The key is a concatenation, not a hash

Do not hash the two authenticity numbers together. The key is the raw 32-byte concatenation AN_A || AN_B, in that order. Hashing the concatenation is a plausible-looking mistake that produces a completely different key and a tag that never verifies.

Encryption:

plaintext  P = challenge[16] || command_data[N]
ciphertext C = AES-256-GCM-Encrypt(K, nonce, AAD = header[0..47], P)
body         = C || 0x3E 0x3E

The request AAD is header bytes 0–47 — the whole header except the tag itself. The terminator is clear and is not authenticated.

Duplicate-key mode

If only one eligible key coin is available, key B may be the same coin as key A: identical selectors in the header, giving K = AN_A || AN_A. Servers accept this.

Be aware of what it costs: the cipher is still AES-256, but the key carries at most 128 bits of entropy. This is a deliberate client-side trade-off for wallets that hold a single usable key coin, and the client software already handles the choice. Deployments that require a genuine 256-bit security target should disable it and fail when no distinct second coin exists.

Type 8 has no replay protection

The GCM nonce makes each request unique, but the server does not remember nonces it has seen, so a captured type 8 request can be replayed. Type 9 addresses this with an explicit counter; type 8 does not have one. Its seven reserved bytes at 41–47 sit inside the AAD and would be the natural place to add one, but no such mechanism exists today.

Type 9 — AES-256-GCM, keyed by a session handle

Type 9 does not go to a RAIDA

Type 9 is Content Server traffic. A RAIDA rejects it, and that is by design: a RAIDA has no session table, so it has nothing to resolve a session handle against. It is documented here because it shares the same framing as the RAIDA types, not because a RAIDA will answer it.

Type 9 changes exactly one thing relative to type 8: how the key is located. Same cipher, same nonce discipline, same tag position, same AAD span, same 32-byte response frame. Where type 8 names two coins and the server derives a key from its coin database, type 9 names a session and the server looks the key up in its session table.

VR0SP1RI (node)2SH3CG4CM5ID6RS (MUST be zero — no overloads)8EN=916HD (Session handle, 5 bytes)17BL (32-bit)22BL24NO (Nonce)26NO (Nonce continues)32CT (counter)38CT (req_counter, 8 bytes BE)40RS46AT (GCM Auth Tag)48AT (GCM Auth Tag continues)56
BytesFieldRequirement
2RIThe Content Server's published node_idnot a RAIDA index. A CS configured with a nonzero node ID rejects a mismatch as malformed; a CS with node ID 0 accepts any value and echoes it.
8–15RSMUST be zero. The Group 6 extended framing that overloads these bytes under type 1 is disabled under type 9; large-object paging moves into the command data instead.
16ENMUST be 0x09.
17–21HDThe 5-byte session handle, copied verbatim. It is opaque — no integer interpretation, therefore no endianness. All-zero is reserved and means "this is a session-open request".
22–25BL32-bit big-endian body length, including the terminator. Four bytes, not two — there is no 64 KB cap here.
26–37NO12-byte GCM nonce. The most significant bit of byte 26 MUST be 0 on requests.
38–45CT64-bit big-endian request counter. Zero for a session-open request; 1 or greater for an established session. Replays are refused with status 103.
46–47RSMUST be zero. Authenticated via the AAD.
48–63ATFull 16-byte GCM tag.

Key lookup:

HandleKeyMeaning
All zeroK_rke, recomputed from the vault and the open contextSession-open request
NonzeroK_sess, from the session tableEstablished-session command

The handle is a lookup selector, never a secret. Possession of the GCM key is what authenticates the caller. Coin authenticity numbers never appear on this wire at all — which is the point, since a Content Server is not trusted to hold them.

Challenge: type 9 keeps the 16-byte challenge and validates it. After the GCM tag verifies, the server checks the CRC32 and answers with status 37 on a mismatch.

The RKE key ID is not the session handle

These are easy to confuse and are different things. The RKE key ID is a one-byte vault index used when deriving K_rke from RAIDA-held shares. The session handle is five opaque bytes that locate an already-established session key. Only the handle appears in the type 9 header.

The other type numbers

None of the remaining numbers are available to client software. A request carrying an unimplemented type is rejected with ERROR_INVALID_ENCRYPTION (34).

  • Types 3 and 7 are reserved for traffic between servers. Client software cannot use them: the keys involved are held only by servers.
  • Types 4 and 5 are an earlier AES-256 design, superseded by type 8. The client library does not support them and no live command accepts them. Do not build anything new on them.
  • Type 6 has never been allocated. It is simply a gap in the numbering.