Deterministic Serialization
1. General Encoding Rules
All multi-byte integers are:
- Unsigned
- Big-endian (network byte order)
The following base types are used:
uint8– 1 byteuint16– 2 bytesuint32– 4 bytes
The following composite type is used:
opaque X<0..2^16-1>– a 16-bit length-prefixed byte string:- First:
uint16 length - Then:
lengthbytes of data
- First:
2. ClientHelloPALISADE Structure (Logical View)
The ClientHelloPALISADE message consists of the following fields, encoded exactly as specified below (per Section 7.1 of the PALISADE specification):
version– PALISADE protocol version (1 byte, e.g., 0x12 for v1.2)supported_kems[]– ordered list of KEM identifiers (count + IDs)supported_sigs[]– ordered list of signature algorithm identifiers (count + IDs)supported_aeads[]– ordered list of AEAD algorithm identifiers (count + IDs)client_nonce– 32-byte random nonce (fixed size, no length prefix)K_c– client ephemeral KEM public key (length-prefixed)client_certificate– client certificate (length-prefixed, mandatory for full handshakes)client_signature– optional client signature (length-prefixed, 0 if absent)padding– optional padding (length-prefixed, 0 if absent)extensions– list of extensions (count + variable, 0 if absent)
All fields have exactly one on-the-wire representation, including optional fields.
3. ClientHelloPALISADE Binary Layout
The binary layout is (per Section 7.1 of the PALISADE specification):
struct {
uint8 version; // PALISADE protocol version (e.g., 0x12 for v1.2)
uint16 supported_kems_count; // number of KEM identifiers
uint16 supported_kems[]; // array of KEM identifiers (count * 2 bytes)
uint16 supported_sigs_count; // number of signature identifiers
uint16 supported_sigs[]; // array of signature identifiers (count * 2 bytes)
uint16 supported_aeads_count; // number of AEAD identifiers
uint16 supported_aeads[]; // array of AEAD identifiers (count * 2 bytes)
opaque client_nonce[32]; // 32 bytes, not length-prefixed
opaque K_c<0..2^16-1>; // client ephemeral KEM public key
opaque client_certificate<0..2^16-1>; // client certificate (mandatory for full handshakes)
opaque client_signature<0..2^16-1>; // OPTIONAL (len=0 if absent)
opaque padding<0..2^16-1>; // OPTIONAL (len=0 if absent)
uint16 extensions_count; // number of extensions
Extension extensions[]; // array of Extension structures
} ClientHelloPALISADE;Notes:
versionis a single byte (e.g.,0x12for PALISADE v1.2).supported_kems[],supported_sigs[], andsupported_aeads[]are encoded as a 2-byte count followed by the list of 2-byte identifiers.client_nonceis always present and is exactly 32 bytes (no length prefix).K_c,client_certificate,client_signature, andpaddingare encoded as length-prefixed opaque values (2-byte length + data).extensionsis encoded as a 2-byte count followed by the Extension structures (see Section 6).
4. Optional Field Canonicalization
For client_identity and client_certificate:
If the field is logically absent, it MUST be encoded as:
uint16 length = 0 // no following bytes
If the field is present, it MUST be encoded as:
uint16 length = N uint8 data[N]
There is no alternate encoding for absence or emptiness. Length 0 is the only valid representation of an absent optional field.
This ensures:
One logical message → one unique byte encoding.
Any other encoding (e.g., zeroed data with non-zero length) MUST be treated as invalid.
5. Extensions Block
The extensions field is itself a 16-bit length-prefixed vector of Extension structures:
opaque extensions<0..2^16-1>;
Where the content of extensions is:
struct {
uint16 extension_type;
opaque extension_data<0..2^16-1>;
} Extension;
struct {
// concatenation of zero or more Extension structures
Extension extensions_list<0..2^16-1>;
} ExtensionsVector;6.1 Canonical Ordering
To ensure determinism:
- Extensions MUST be sorted in strictly increasing order of
extension_type. - Each
extension_typeMUST appear at most once. - Unknown extensions MUST be ignored by receivers but MUST be preserved verbatim by intermediaries (if any).
6.2 Empty Extensions
If no extensions are present:
- The
extensionsfield MUST be encoded withlength = 0and no following bytes.
6. Transcript Serialization for ClientHello
For the purpose of transcript hashing and signatures (per Section 7.5 of the PALISADE specification):
The canonical serialized form of ClientHelloPALISADE excludes:
client_signature— excluded to prevent circular dependency (signature cannot include itself)padding— explicitly non-canonical for traffic analysis resistance
The canonical ClientHello for transcript hashing includes exactly the bytes:
version(1 byte),supported_kems_count(2 bytes) +supported_kems[](count * 2 bytes),supported_sigs_count(2 bytes) +supported_sigs[](count * 2 bytes),supported_aeads_count(2 bytes) +supported_aeads[](count * 2 bytes),client_nonce(32 bytes),K_copaque (2-byte length + bytes),client_certificateopaque (2-byte length + bytes),extensions_count(2 bytes) +extensions[](variable).
There are no alternate encodings, no compression, and no optional elision rules for the canonical transcript form.
7. Example Encoding (Illustrative Only)
As a simple example, a ClientHello with:
version = 0x12(PALISADE v1.2)supported_kems = [0x0011](ML-KEM-768)supported_sigs = [0x0021](ML-DSA-65)supported_aeads = [0x0001](ChaCha20-Poly1305)client_nonce = 32 bytesK_c = 1200 bytes(example ML-KEM-768 public key)client_certificate = 1952 bytes(example)client_signatureabsentpaddingabsentextensionsempty
Would be encoded as:
12 // version (0x12 = v1.2) 00 01 // supported_kems_count = 1 00 11 // supported_kems[0] = ML-KEM-768 00 01 // supported_sigs_count = 1 00 21 // supported_sigs[0] = ML-DSA-65 00 01 // supported_aeads_count = 1 00 01 // supported_aeads[0] = ChaCha20-Poly1305 <32 bytes> // client_nonce 04 B0 // K_c length (0x04B0 = 1200) <1200 bytes> // K_c 07 A0 // client_certificate length (0x07A0 = 1952) <1952 bytes> // client_certificate 00 00 // client_signature length = 0 (absent) 00 00 // padding length = 0 (absent) 00 00 // extensions_count = 0 (no extensions)
For transcript hashing, exclude client_signature and padding from the above sequence.
8. ServerHelloPALISADE Structure (Logical View)
The ServerHelloPALISADE message consists of the following fields, encoded exactly as specified below (per Section 7.2 of the PALISADE specification):
version– negotiated PALISADE protocol version (1 byte, e.g., 0x12 for v1.2)kem_choice– selected KEM identifier (2 bytes)sig_choice– selected signature algorithm identifier (2 bytes)aead_choice– selected AEAD algorithm identifier (2 bytes)server_nonce– 32-byte random nonce (fixed size, no length prefix)K_s– server ephemeral KEM public key (length-prefixed)CT_c– ciphertext from encapsulation to client's K_c (length-prefixed)CT_s– ciphertext from encapsulation to server's K_s (length-prefixed)server_certificate– server's long-term post-quantum public key (length-prefixed)server_signature– digital signature over handshake transcript (length-prefixed)dos_cookie– optional DoS protection cookie (length-prefixed, 0 if absent)padding– optional padding for traffic analysis resistance (length-prefixed, 0 if absent)extensions– list of extensions (count + variable, 0 if absent)
All fields have exactly one on-the-wire representation, including optional fields.
9. ServerHelloPALISADE Binary Layout
The binary layout is (per Section 7.2 of the PALISADE specification):
struct {
uint8 version; // negotiated version (e.g. 0x12 for v1.2)
uint16 kem_choice; // selected KEM identifier
uint16 sig_choice; // selected signature identifier
uint16 aead_choice; // selected AEAD identifier
opaque server_nonce[32]; // 32 bytes, not length-prefixed
opaque K_s<0..2^16-1>; // server ephemeral KEM public key
opaque CT_c<0..2^16-1>; // ciphertext to client's K_c
opaque CT_s<0..2^16-1>; // ciphertext to server's K_s
opaque server_certificate<0..2^16-1>; // server long-term public key
opaque server_signature<0..2^16-1>; // signature over transcript
opaque dos_cookie<0..2^16-1>; // OPTIONAL (len=0 if absent)
opaque padding<0..2^16-1>; // OPTIONAL (len=0 if absent)
uint16 extensions_count; // number of extensions
Extension extensions[]; // array of Extension structures
} ServerHelloPALISADE;Notes:
versionis a single byte (e.g.,0x12for PALISADE v1.2).server_nonceis always present and is exactly 32 bytes (no length prefix).K_s,CT_c,CT_s,server_certificate, andserver_signatureare mandatory and are encoded as length-prefixed opaque values (2-byte length + data).dos_cookieandpaddingare optional and are encoded as length-prefixed opaque values (2-byte length + data, length 0 if absent).extensionsis encoded as a 2-byte count followed by the Extension structures (see Section 5).
10. ServerHello Optional Field Canonicalization
For dos_cookie and padding:
If the field is logically absent, it MUST be encoded as:
uint16 length = 0 // no following bytes
If the field is present, it MUST be encoded as:
uint16 length = N uint8 data[N]
There is no alternate encoding for absence or emptiness. Length 0 is the only valid representation of an absent optional field.
The same canonicalization rules from Section 5 apply to ServerHello optional fields.
11. Transcript Serialization for ServerHello
For the purpose of transcript hashing and signatures (per Section 7.5 of the PALISADE specification):
The transcript contribution of ServerHelloPALISADE excludes the following fields:
server_signature— excluded to prevent circular dependency (signature cannot include itself)dos_cookie— excluded as it is not part of security-critical negotiationpadding— explicitly non-canonical for traffic analysis resistance
The canonical ServerHello for transcript hashing includes exactly the bytes:
version(1 byte),kem_choice(2 bytes),sig_choice(2 bytes),aead_choice(2 bytes),server_nonce(32 bytes),K_sopaque (2-byte length + bytes),CT_copaque (2-byte length + bytes),CT_sopaque (2-byte length + bytes),server_certificateopaque (2-byte length + bytes),extensions_count(2 bytes) +extensions[](variable).
There are no alternate encodings, no compression, and no optional elision rules for the canonical transcript form.
12. ServerHello Example Encoding (Illustrative Only)
As a simple example, a ServerHello with:
version = 0x12(PALISADE v1.2)kem_choice = 0x0011(ML-KEM-768)sig_choice = 0x0021(ML-DSA-65)aead_choice = 0x0001(ChaCha20-Poly1305)server_nonce = 32 bytesK_s = 1200 bytes(example ML-KEM-768 public key)CT_c = 1120 bytes(example ML-KEM-768 ciphertext)CT_s = 1120 bytes(example ML-KEM-768 ciphertext)server_certificate = 1952 bytes(example ML-DSA-65 public key)server_signature = 2420 bytes(example ML-DSA-65 signature)dos_cookieabsentpaddingabsentextensionsempty
Would be encoded as:
12 // version (0x12 = v1.2) 00 11 // kem_choice (ML-KEM-768) 00 21 // sig_choice (ML-DSA-65) 00 01 // aead_choice (ChaCha20-Poly1305) <32 bytes> // server_nonce 04 B0 // K_s length (0x04B0 = 1200) <1200 bytes> // K_s 04 60 // CT_c length (0x0460 = 1120) <1120 bytes> // CT_c 04 60 // CT_s length (0x0460 = 1120) <1120 bytes> // CT_s 07 A0 // server_certificate length (0x07A0 = 1952) <1952 bytes> // server_certificate 09 74 // server_signature length (0x0974 = 2420) <2420 bytes> // server_signature 00 00 // dos_cookie length = 0 (absent) 00 00 // padding length = 0 (absent) 00 00 // extensions_count = 0 (no extensions)
For transcript hashing, exclude server_signature, dos_cookie, and padding from the above sequence.
13. Rationale
Deterministic serialization is security-critical for authenticated key exchange protocols because cryptographic operations such as transcript hashing and digital signatures operate over byte sequences, not abstract message structures. If a single logical message admits multiple valid encodings, different protocol participants may compute divergent transcripts, enabling signature verification failures, downgrade attacks, or subtle misbinding vulnerabilities. Non-canonical encodings have historically led to security flaws in protocols that rely on implicit or underspecified serialization rules. By defining exactly one valid on-the-wire representation for each logical handshake message, including optional fields and extensions, PALISADE ensures that all participants compute identical transcripts under all conditions. This eliminates entire classes of ambiguity-based attacks, simplifies implementation, and enables reliable interoperability without reliance on complex or context-dependent encoding frameworks.
PALISADE Protocol Specification Draft 00
INFORMATIONAL