Response Headers
A fixed 32-byte frame. The first sixteen bytes are the same for every encryption type; the last sixteen are how the server proves the response is genuine, and those differ by type.
Bytes 0–15: the same for every type
| Bytes | Field | Meaning |
|---|---|---|
| 0 | RI | The responding RAIDA's index, or a Content Server's node ID echoed back under type 9. |
| 1 | SH | Shard ID. Zero. |
| 2 | ST | Status code. The single most important byte in the response. 250 is success; everything else is documented on the command's own page. |
| 3 | CG | Command group, echoed from the request. |
| 4–5 | FC | Frame count. Always 1. |
| 6–7 | EC | Client echo, returned from request bytes 30–31. Types 8 and 9 always send zero here — the echo is deferred in both specifications. |
| 8 | RS | Reserved, zero. The object transfer commands (6/76–84) overload this as a framing version. |
| 9–11 | BL | Response body length, 24-bit big-endian. Note this is a different width from any request length field. |
| 12–15 | ET | Server execution time, 32-bit big-endian microseconds. The object transfer commands repurpose these bytes as part of a 32-bit body length. |
Types 0, 1, 2 — bytes 16–31 carry a challenge proof
The server returns a 16-byte value derived from the challenge the client sent in its request body. Under type 0 this is the challenge echoed back; under types 1 and 2 it is a proof combining the challenge with the key coin's authenticity number — something only a server that genuinely holds that AN could produce.
This is the older authentication model: the header proves the responder is genuine, while the body's integrity rests on the challenge CRC32. It is not authenticated encryption, and it does not detect tampering with the response body itself.
Types 8 and 9 — bytes 16–31 carry a GCM tag
The same sixteen bytes now hold the response's AES-256-GCM authentication tag. This is a genuine upgrade rather than a relabelling: the tag covers both the header and the response body, so a client that verifies it knows the entire response is untampered, not merely that the responder knew a secret.
| Property | Value |
|---|---|
| Response AAD | Response header bytes 0–15 |
| Tag position | Bytes 16–31, full 16 bytes |
| Key | Same key as the request |
| Nonce | Not transmitted. Derived locally from the request nonce. |
Why the response nonce is not on the wire
The response nonce is the request nonce with its direction bit set: requests have the most significant bit of the nonce's first byte at 0, responses at 1. This partitions the nonce space so a request nonce and a response nonce can never collide under the same key — which is the property GCM requires.
The practical consequence for a client: keep the request nonce until the response has been verified. You cannot recover it from the response.
Reusing the 32-byte legacy frame for a modern AEAD cipher was deliberate. It meant type 8 could ship without changing the transport layer or any response parser — the frame is the same size and shape, and only the meaning of the last sixteen bytes changed.
The unauthenticated failure frame
A zero tag means the server could not authenticate you
When a type 8 or type 9 request cannot be authenticated at all — the key coin is unknown, the session handle does not resolve, or the GCM tag fails to verify — the server has no shared key, and therefore cannot produce a valid tag. It returns a fixed 32-byte frame with bytes 16–31 all zero and a zero body length.
Clients MUST handle this case explicitly. Do not treat a failed tag verification as a network error or a corrupt packet: check for the all-zero tag with a zero body length first, and read the status byte, which carries the real reason.
Type 9 defines named statuses for these conditions, including unknown handle (102), counter replay (103), capacity (104), authentication failed (105) and malformed (106).
Parsing pitfalls
| Trap | What to do |
|---|---|
| Assuming the body length is 16-bit because request lengths often are | The response length is 24-bit, at bytes 9–11. It matches no request length field in the protocol. |
| Expecting your echo bytes back under type 8 or 9 | They are always zero. Match requests to responses by connection, not by echo. |
| Discarding the request nonce after sending | You need it to derive the response nonce. Keep it until verification completes. |
| Treating a zero tag as corruption | It is a defined failure frame. Read the status byte. |
| Reading bytes 8 and 12–15 as reserved and execution time for object transfer commands | Commands 6/76–84 repurpose them for extended framing. See the object transfer pages. |