StreamMessage Envelope
The StreamMessage is the fundamental wrapper for all S2 communication. It provides routing information, a unique message ID, and the encrypted payload. Complete StreamMessage objects are tunneled across the DLT network using the s2data core protocol message.
Core Data Types
IxiVarInt/IxiVarUInt: See IxiVarInt Encoding.IxiBytes: See IxiBytes Encoding.bool: A single byte,0x00forfalseand0x01fortrue.
Serialization Structure (v1)
| Field | Data Type | Description |
|---|---|---|
version | IxiVarUInt | The StreamMessage version (currently 1). |
id | IxiBytes | A unique identifier for this message. |
type | IxiVarUInt | The message type. See StreamMessageCode table below. |
encryptionType | IxiVarUInt | The encryption scheme used. See StreamMessageEncryptionCode table below. |
sender | IxiBytes | The wallet address (without checksum) of the original sender. |
recipient | IxiBytes | The wallet address (without checksum) of the final recipient. |
data | IxiBytes | The encrypted payload, which contains a SpixiMessage. |
timestamp | IxiVarInt | The Unix timestamp of the message's creation. |
signature | IxiBytes | A signature over the message checksum. Present and required if encryptionType is rsa2. Not included in checksum. |
requireRcvConfirmation | bool | A flag indicating if a delivery confirmation is expected. Not included in checksum. |
StreamMessageCode
| Code | Name | Description |
|---|---|---|
0 | error | An error message, sent only by S2 nodes (e.g., routing failure). |
1 | info | A free, rate-limited message type for low-priority data. |
2 | data | The standard message type for general data. |
StreamMessageEncryptionCode
| Code | Name | Description |
|---|---|---|
3 | rsa2 | (Handshake) A key-wrapping scheme for securely transporting key exchange materials (e.g., ML-KEM public keys). The payload is encrypted using the recipient's long-term RSA key for confidentiality, while the message's signature provides authenticity from the sender, preventing man-in-the-middle attacks. |
4 | spixi2 | (Data Transfer) A robust AEAD scheme deriving per-message keys for encrypting the actual data after a secure session has been established. |
Signature Generation
- The
StreamMessageis serialized excluding thesignatureandrequireRcvConfirmationfields. - The
sha3_512hash of this serialized data is calculated. This is thechecksum. - The
signatureis a standard RSA signature of thischecksum, created using thesender's private key.
Cryptographic Context
StreamMessage encryption schemes plug into the composite primitives defined in Cryptographic Primitives. Base long‑lived symmetric keys (AES‑256 and ChaCha20) are derived from the hybrid shared secret described there; this document only specifies how they are consumed at the envelope layer.
Checksum & Integrity
| Version | Hash Function | Checksum Input | Excludes |
|---|---|---|---|
1 | sha3_512 | Serialization type checksum | signature, requireRcvConfirmation |
The checksum authenticates all routing and cryptographic metadata except the two excluded fields. When rsa2 is used, the signature is is computed over the checksum.
AEAD Associated Data (AAD)
For all schemes using AEAD (spixi2, inner portion of rsa2), the AAD MUST be:
AAD = id || IxiVarUInt(type) || IxiVarInt(timestamp)
This binds the message ID, type, and timestamp to the encryption, preventing undetected tampering even if the outer envelope is unsigned.
rsa2 Payload Structure (Handshake Transport)
rsa2 wraps a one‑time spixi2 encryption with an RSA‑4096 key wrap of ephemeral symmetric keys. It does not transport the long‑lived base keys (those come from the hybrid secret process in the primitives spec); instead it enables a sender to deliver a single encrypted message to a recipient for whom only the RSA public key is known.
Steps (sender side):
- Generate 32‑byte ephemeral AES key
K_AES_eand 32‑byte ephemeral ChaCha keyK_CHACHA_eusing a secure RNG. - Perform
spixi2encryption of the plaintext usingK_AES_e,K_CHACHA_e(see below) with AAD defined above. Result:Cipher_spixi2. - Encode
K_AES_eandK_CHACHA_eeach asIxiBytes, concatenate ->EphemeralKeysBlob. - RSA‑encrypt
EphemeralKeysBlobwith recipient's RSA‑4096 public key. Result:EncryptedKeys(encoded asIxiBytes). - Concatenate
EncryptedKeys || Cipher_spixi2. This byte stream becomes thedatafield of theStreamMessage. - Compute checksum and create RSA signature (required for
rsa2).
Receiver side:
- Parse
EncryptedKeys(firstIxiBytes). - RSA‑decrypt -> split back into two
IxiBytes->K_AES_e,K_CHACHA_e. - Decrypt remaining bytes with
spixi2using recovered ephemeral keys and AAD. - (If present) Verify signature over checksum before accepting payload.
spixi2 Payload Structure (Per-Message Key Derivation)
spixi2 provides two layers of AEAD (AES‑GCM then ChaCha20‑Poly1305) with per‑message derived keys and IVs to eliminate nonce/key reuse risks.
Steps (sender side):
- Generate a 64‑byte
message_noncevia secure RNG. - Derive per‑message AES secret:
H_AES = sha3_512sq( baseAES || message_nonce ).key_AES = H_AES[0..31]iv_AES = H_AES[32..43](12 bytes for GCM)
- Encrypt plaintext with AES‑GCM using
key_AES,iv_AES, AAD. - Derive per‑message ChaCha secret:
H_CHACHA = sha3_512sq( baseChaCha || message_nonce ).key_CHACHA = H_CHACHA[0..31]iv_CHACHA = H_CHACHA[32..43](12 bytes for ChaCha20‑Poly1305 variant)
- Encrypt AES ciphertext with ChaCha20‑Poly1305 using
key_CHACHA,iv_CHACHA, same AAD. - Encode
message_nonceasIxiBytes, then append the length‑prefixed ChaCha ciphertext. Result becomesdata.
Receiver side:
- Read
message_nonce(IxiBytes). - Derive
key_CHACHA,iv_CHACHAwith base ChaCha key and nonce; decrypt outer layer (ChaCha20‑Poly1305) using AAD. - Derive
key_AES,iv_AESwith base AES key and nonce; decrypt inner layer (AES‑GCM). - Output plaintext payload (which is a serialized
SpixiMessage).
Reproduction Summary
To reproduce envelope cryptography:
- Obtain or derive base symmetric keys (see Cryptographic Primitives) for the peer session.
- Build AAD exactly as specified.
- Choose encryption type:
rsa2: follow rsa2 steps; sign checksum.spixi2: follow spixi2 steps; signature optional (not used unless explicitly set viarsa2).
- Serialize fields; compute checksum (version‑dependent hash); append signature if required.
- Wrap entire serialized object in the outer transport (
s2datamessage) unchanged.
Security Properties (Informative)
| Property | Mechanism |
|---|---|
| Replay resistance (payload) | Nonce‑derived per‑message keys (message_nonce) |
| Integrity of routing fields | Checksum + optional RSA signature |
Confidentiality (spixi2) | Dual Encryption (AES‑GCM -> ChaCha20‑Poly1305) |
Ephemeral confidentiality (rsa2) | RSA key wrap of symmetric keys |
| Tamper detection (unsigned) | AEAD AAD binding id, type, timestamp |