Low Security Request Headers
Encryption types 0, 1 and 2. A 32-byte header, with either no encryption or AES-128. These protect a body from casual inspection; they do not detect tampering.
Choose these only when a command requires them
None of these types provide authenticated encryption. Body integrity rests on a CRC32 carried inside the challenge, which catches accidental corruption but not deliberate modification — an attacker able to alter packets in flight will not be detected by it. The header is not protected at all.
Most live RAIDA traffic is type 1 today for historical reasons, and several commands still require it. For anything new, prefer High Security (types 8 and 9): AES-256-GCM, with the header authenticated alongside the body.
What they share
All three use a 32-byte request header and a 32-byte response header. The decrypted body begins with a 16-byte challenge, so the command payload starts at body offset 16.
| Property | Type 0 | Type 1 | Type 2 |
|---|---|---|---|
| Cipher | none | AES-128-CTR | AES-128-CTR |
| Key source | — | one coin's AN | locker AN by prefix |
| Body length at | 22–23 | 22–23 | 22–23 |
| Length width | 16-bit | 16-bit | 16-bit |
| Client echo | 30–31 | 30–31 | 30–31 |
| Body integrity | CRC32 | CRC32 | CRC32 |
| Header authenticated | no | no | no |
| Replay protection | none | none | none |
The 64 KB body limit
All three carry a 16-bit body length, capping a single request body at 65,535 bytes. This is a real constraint on protocol design: any new field added to a request body competes for an already-tight budget. High Security type 9 escapes the cap with a 32-bit field; these types do not.
Type 0 — No encryption
Type 0 is refused by default
A production RAIDA rejects every type 0 request with ERROR_INVALID_ENCRYPTION (34) unless the operator has explicitly enabled a node-wide allow_type0 flag. This is a deliberate guard: without it, any client could force an encrypted node down to cleartext simply by setting one header byte.
If you are testing against a node and every type 0 request fails with status 34, the node has not opted in. This is the most common cause of that error, and it is not something a client can fix.
The RKE commands (group 15) require a second, separate flag on top of this one before they will accept type 0 — so enabling allow_type0 alone does not open a cleartext path to key material.
| Bytes | Field | Notes |
|---|---|---|
| 0 | VR | Router version. Normally 0x01. |
| 1 | SP | Split ID. Normally zero. |
| 2 | RI | Target RAIDA index, 0–24. One packet targets one RAIDA; clients fan out. |
| 3 | SH | Shard ID. Zero for non-sharded traffic. |
| 4–5 | CG / CM | Command group and command code. Two independent bytes, not one packed number. |
| 6–7 | ID | Coin type. CloudCoin is 0x0006. This is the network constant, not the caller's coin. |
| 8–15 | PR / RS | Presentation and reserved. Zero. |
| 16 | EN | 0x00. |
| 17–21 | — | No key selector; there is no key. Zero. |
| 22–23 | BL | Body length, 16-bit big-endian, including the 2 terminator bytes. |
| 24–29 | — | No nonce. The server zeroes its nonce buffer. |
| 30–31 | EC | Client echo. Returned verbatim in the response header, for matching replies without parsing the body. |
Body: challenge[16] || command_data[N] || 0x3E 0x3E, all cleartext. The challenge is 12 random bytes followed by their CRC32; the server validates the CRC and echoes the challenge back.
Type 1 — AES-128-CTR, keyed by one coin
This is the workhorse. Almost all live RAIDA traffic is type 1.
| Bytes | Field | Notes |
|---|---|---|
| 0–15 | as type 0 | Routing, command, coin type, reserved. |
| 16 | EN | 0x01. |
| 17 | DN | Denomination of the key coin. |
| 18–21 | SN | Serial number of the key coin, big-endian. |
| 22–23 | BL | Body length, 16-bit big-endian, including the terminator. |
| 24–31 | NO | 8 nonce bytes. The server copies these into a 16-byte buffer and leaves the rest zero. Bytes 30–31 double as the client echo EC. |
Key: the 16-byte Authenticity Number of the coin named at bytes 17–21, used raw — no hashing. The server looks the coin up in its own database, so the key never travels.
Body: AES-128-CTR( challenge[16] || command_data[N] ) || 0x3E 0x3E. The terminator is clear, outside the ciphertext.
The key coin is not the subject coin
Bytes 17–21 name the coin whose AN encrypts the packet. That is frequently a different coin from the one the command is about — a detect request encrypts with one coin and asks about a hundred others. Do not conflate the two.
Type 1 variant: commands 76–84 (QMail object transfer)
The object transfer commands replace the 16-bit body length with a 32-bit one, so that a single range transfer is not capped at 65,535 bytes. They do it by reusing header bytes that are reserved under every other type 1 command: byte 9 becomes a framing version, bytes 10–13 the real body length, and bytes 22–23 must carry an 0xFFFF sentinel in place of a length.
The complete byte layout, for both request and response, is on the Object Transfer overview.
These commands also add two hard requirements, both checked before the server allocates a body:
- TCP only. A request arriving over UDP is refused with
ERROR_TCP_REQUIRED(218). - Type 1 only. Any other encryption type is refused with
ERROR_UNSUPPORTED_PROTOCOL(219).
See the Object Transfer overview for the per-command framing.
Type 2 — AES-128-CTR, keyed by a locker
Identical to type 1 in every respect except where the key comes from. Bytes 17–21 are not a denomination and serial number; they are a 5-byte locker index prefix. The server looks that prefix up in its locker index and uses the associated 16-byte AN as the AES-128 key.
If no locker matches the prefix, the request fails with ERROR_INVALID_ENCRYPTION (34).