Skip to main content

SST Message Types

SST defines a fixed set of message types used across the three communication planes: entity-to-Auth, entity-to-entity (session key handshake and secure communication), and Auth-to-Auth. Every SST message carries a one-byte type code. The canonical source of truth is MessageType.java.

IoTSP framing

All SST messages — entity-to-Auth, Auth-to-Auth, and entity-to-entity — share the same outer envelope, serialized by serializeIoTSP() in common.js and its Java counterpart IoTSPMessage.java:

┌──────────┬──────────────────────────┬───────────┐
│ msgType │ payloadLen │ payload │
│ (1 byte) │ (variable-length int) │ (N bytes) │
└──────────┴──────────────────────────┴───────────┘
  • msgType: one of the values in the summary table below.
  • payloadLen: the byte length of payload, encoded as a variable-length integer.
  • payload: message-specific content; structure varies by type and is described in each section below.

Summary table

CodeNamePlaneDirection
0AUTH_HELLOEntity ↔ AuthAuth → Entity
1ENTITY_HELLOEntity ↔ AuthEntity → Auth
10AUTH_SESSION_KEY_REQAuth ↔ AuthAuth → Auth
11AUTH_SESSION_KEY_RESPAuth ↔ AuthAuth → Auth
20SESSION_KEY_REQ_IN_PUB_ENCEntity ↔ AuthEntity → Auth
21SESSION_KEY_RESP_WITH_DIST_KEYEntity ↔ AuthAuth → Entity
22SESSION_KEY_REQEntity ↔ AuthEntity → Auth
23SESSION_KEY_RESPEntity ↔ AuthAuth → Entity
24SESSION_KEY_RESP_FOR_DELEGATIONEntity ↔ AuthAuth → Entity
25SESSION_KEY_RESP_FOR_DELEGATION_WITH_DIST_KEYEntity ↔ AuthAuth → Entity
30SKEY_HANDSHAKE_1Entity ↔ EntityInitiator → Responder
31SKEY_HANDSHAKE_2Entity ↔ EntityResponder → Initiator
32SKEY_HANDSHAKE_3Entity ↔ EntityInitiator → Responder
33SECURE_COMM_MSGEntity ↔ EntityBidirectional
34FIN_SECURE_COMMEntity ↔ EntityBidirectional
40SECURE_PUBEntity ↔ EntityPublisher → Subscriber
50MIGRATION_REQ_WITH_SIGNEntity ↔ AuthEntity → Auth
51MIGRATION_RESP_WITH_SIGNEntity ↔ AuthAuth → Entity
52MIGRATION_REQ_WITH_MACEntity ↔ AuthEntity → Auth
53MIGRATION_RESP_WITH_MACEntity ↔ AuthAuth → Entity
60ADD_READER_REQ_IN_PUB_ENCEntity ↔ AuthEntity → Auth
61ADD_READER_RESP_WITH_DIST_KEYEntity ↔ AuthAuth → Entity
62ADD_READER_REQEntity ↔ AuthEntity → Auth
63ADD_READER_RESPEntity ↔ AuthAuth → Entity
70DELEGATED_ACCESS_REQ_IN_PUB_ENCEntity ↔ AuthEntity → Auth
71DELEGATED_ACCESS_RESP_WITH_DIST_KEYEntity ↔ AuthAuth → Entity
72DELEGATED_ACCESS_REQEntity ↔ AuthEntity → Auth
73DELEGATED_ACCESS_RESPEntity ↔ AuthAuth → Entity
80PRIVILEGED_REQ_IN_PUB_ENCEntity ↔ AuthEntity → Auth
81PRIVILEGED_RESP_WITH_DIST_KEYEntity ↔ AuthAuth → Entity
82PRIVILEGED_REQEntity ↔ AuthEntity → Auth
83PRIVILEGED_RESPEntity ↔ AuthAuth → Entity
100AUTH_ALERTEntity ↔ AuthAuth → Entity

Entity ↔ Auth messages

These messages flow between an entity and the Auth it is registered to. They cover the initial greeting, session key acquisition, and error signaling.

AUTH_HELLO (0)

Sent by Auth to open the authentication handshake. The entity must reply with ENTITY_HELLO (or a session key request variant) using the nonce supplied here.

FieldTypeDescription
authIdUInt32BE (4 B)Identifier of the Auth instance
authNonceBuffer (AUTH_NONCE_SIZE)Random nonce for replay protection

ENTITY_HELLO (1)

Greeting sent by an entity in response to AUTH_HELLO.

SESSION_KEY_REQ_IN_PUB_ENC (20)

Entity requests session keys. The payload is encrypted with Auth's public key (used before a distribution key has been established).

FieldTypeDescription
entityNonceBufferEntity-generated nonce
authNonceBufferEcho of the nonce received in AUTH_HELLO
numKeysUInt32BENumber of session keys requested
senderNamelength-prefixed StringRequesting entity's registered name
purposeJSON objectCommunication purpose (describes the target group or key ID)
diffieHellmanParamBuffer (optional)DH parameter for forward-secrecy key exchange

SESSION_KEY_RESP_WITH_DIST_KEY (21)

Auth responds with session keys and the entity's distribution key. Used on first contact or after key rotation.

FieldTypeDescription
entityNonceBufferEcho of the entity nonce from the request
cryptoSpecJSONCipher and MAC algorithm identifiers
sessionKeyListlength-prefixed listOne or more SessionKey objects
encryptedDistKeyBufferThe entity's distribution key, encrypted

SESSION_KEY_REQ (22)

Standard session key request. The payload is encrypted with the entity's existing distribution key rather than Auth's public key.

Fields are identical to SESSION_KEY_REQ_IN_PUB_ENC.

SESSION_KEY_RESP (23)

Auth responds with session keys only (no distribution key). Used when the entity already holds a valid distribution key.

FieldTypeDescription
entityNonceBufferEcho of the entity nonce
cryptoSpecJSONCipher and MAC algorithm identifiers
sessionKeyListlength-prefixed listOne or more SessionKey objects

SESSION_KEY_RESP_FOR_DELEGATION (24)

Session key response for delegated access. Includes an otherSessionKeyOwnerGroup field identifying the group that owns the returned session keys.

SESSION_KEY_RESP_FOR_DELEGATION_WITH_DIST_KEY (25)

Combines the delegated-access response with a distribution key, analogous to the relationship between (21) and (23).

AUTH_ALERT (100)

Auth sends this message to signal an error during entity communication. The payload is a single-byte alert code.

Alert codeValueMeaning
INVALID_DISTRIBUTION_KEY0The distribution key presented by the entity is not recognized
INVALID_SESSION_KEY_REQ1The session key request could not be validated
UNKNOWN_INTERNAL_ERROR2An unspecified internal error occurred in Auth

Auth ↔ Auth messages

These messages flow between two trusted Auth instances, for example when Auth A needs to retrieve session keys on behalf of an entity registered to Auth B.

AUTH_SESSION_KEY_REQ (10)

Sent by one Auth to another to request session keys for a registered entity. Transmitted over HTTP.

FieldTypeDescription
sessionKeyIDLongID of the session key being requested
requestingEntityNameStringName of the entity on whose behalf the request is made
requestingEntityGroupStringGroup of the requesting entity
cachedKeyAuthIDIntID of the Auth that cached the key originally

AUTH_SESSION_KEY_RESP (11)

Response from Auth carrying the requested session keys. Transmitted over HTTP.

FieldTypeDescription
sessionKeyListJSON arrayOne or more SessionKey objects serialized as JSON strings

Entity ↔ Entity messages (session key handshake)

After an entity has obtained session keys from Auth, it establishes a secure channel to a peer using a three-message handshake, then exchanges application data as SECURE_COMM_MSG messages.

State machines

Initiator (client) — implemented in iotSecureClient.js:

IDLE (0) ──send HANDSHAKE_1──► HANDSHAKE_1_SENT (10) ──recv HANDSHAKE_3 ack──► IN_COMM (30)

Responder (server) — implemented in iotSecureServer.js:

IDLE (0) ──recv HANDSHAKE_1──► HANDSHAKE_1_RECEIVED (21) ──send HANDSHAKE_2──► HANDSHAKE_2_SENT (22) ──recv HANDSHAKE_3──► IN_COMM (30)

A WAITING_SESSION_KEY (20) state is entered if the responder needs to request the session key from Auth before proceeding.

Handshake message body format

All three handshake payloads share a common serialized body (from serializeHandshake()) that is then symmetrically encrypted and authenticated:

┌──────────────┬────────────────────────┬────────────────────────┬──────────────────────────┐
│ indicator │ nonce │ replyNonce │ dhParam (optional) │
│ (1 byte) │ (HS_NONCE_SIZE = 8 B) │ (HS_NONCE_SIZE = 8 B) │ (variable) │
└──────────────┴────────────────────────┴────────────────────────┴──────────────────────────┘

The indicator byte is a bitmask controlling which fields carry meaningful data:

BitMaskField present
00x01nonce
10x02replyNonce
20x04dhParam

Space for both nonces is always allocated; unused slots are zeroed.

SKEY_HANDSHAKE_1 (30) — Initiator → Responder

Establishes which session key to use and proves the initiator holds it.

Payload layout:

┌──────────────────────────────┬──────────────────────────────────────────────────────────┐
│ sessionKeyId (plaintext) │ Encrypt+MAC( indicator | nonce | replyNonce[zeroed] ) │
│ (SESSION_KEY_ID_SIZE = 8 B) │ │
└──────────────────────────────┴──────────────────────────────────────────────────────────┘
  • sessionKeyId: identifies which session key both sides will use; sent in plaintext so the responder can look it up.
  • indicator = 0x01 — only nonce is populated.
  • nonce: initiator's freshly generated 8-byte handshake nonce.
  • The entire handshake body is symmetrically encrypted and authenticated with the session key.

SKEY_HANDSHAKE_2 (31) — Responder → Initiator

Proves the responder holds the same session key by echoing the initiator's nonce, and introduces its own nonce for the initiator to echo back.

Payload layout (entirely encrypted + MACed):

┌──────────┬───────────────────────┬───────────────────────┬──────────────────────────┐
│ indicator│ nonce (responder's) │ replyNonce (echo of │ dhParam (if DH enabled) │
│ (1 B) │ (8 B) │ initiator's nonce, 8B)│ (variable) │
└──────────┴───────────────────────┴───────────────────────┴──────────────────────────┘
  • indicator = 0x03 (nonce + replyNonce), or 0x07 if a DH parameter is appended.
  • nonce: responder's freshly generated handshake nonce.
  • replyNonce: echo of the initiator's nonce from SKEY_HANDSHAKE_1; proves the responder decrypted it correctly.
  • dhParam (optional): responder's DH public key when Diffie-Hellman forward secrecy is configured.

SKEY_HANDSHAKE_3 (32) — Initiator → Responder

Completes mutual authentication by echoing the responder's nonce. After this message both sides transition to IN_COMM.

Payload layout (entirely encrypted + MACed):

┌──────────┬───────────────────────┬────────────────────────────────┬──────────────────────────┐
│ indicator│ nonce (zeroed) │ replyNonce (echo of │ dhParam (if DH enabled) │
│ (1 B) │ (8 B, unused) │ responder's nonce, 8 B) │ (variable) │
└──────────┴───────────────────────┴────────────────────────────────┴──────────────────────────┘
  • indicator = 0x02 (replyNonce only), or 0x06 if a DH parameter is appended.
  • replyNonce: echo of the responder's nonce from SKEY_HANDSHAKE_2; proves the initiator decrypted it correctly.
  • dhParam (optional): initiator's DH public key. After this message both sides compute the shared DH secret and update the session key via updateSymmetricKeyWithKeyFromDH().

SECURE_COMM_MSG (33) — Bidirectional

Carries application data after the handshake completes. The payload is the symmetric-encryption-plus-authentication output of:

┌───────────────────────────────────────────────────────────────────────────┐
│ Encrypt+MAC( seqNum (SEQ_NUM_SIZE = 8 B, big-endian) | data (variable) ) │
└───────────────────────────────────────────────────────────────────────────┘
  • seqNum: monotonically increasing 64-bit counter, tracked separately per direction (writeSeqNum / readSeqNum) to detect replays.
  • data: raw application payload bytes.

FIN_SECURE_COMM (34) — Bidirectional

Signals session teardown.

  • TCP: handled implicitly by the socket end event; no explicit FIN_SECURE_COMM message is sent over the wire.
  • UDP: explicit message with an empty payload is required because UDP has no connection state. The responder transitions back to IDLE and the socket can be reused for a new session.

SECURE_PUB (40) — Publisher → Subscriber

Used in publish/subscribe scenarios (MQTT or UDP broadcast). Because there is no prior handshake, the key ID must be included in plaintext so subscribers can look up the correct session key.

Payload layout:

┌────────────────────────────────┬─────────────────────────────────────────────────────────┐
│ keyId (plaintext) │ Encrypt+MAC( seqNum (8 B, big-endian) | data (variable))│
│ (SESSION_KEY_ID_SIZE = 8 B) │ │
└────────────────────────────────┴─────────────────────────────────────────────────────────┘
  • keyId: identifies which session key from the subscriber's currentSessionKeyList to use for decryption; in plaintext.
  • seqNum: 64-bit monotonically increasing counter for replay detection.
  • data: encrypted application payload.

If a subscriber receives a SECURE_PUB for an unknown keyId, it requests the missing session key from Auth and retries decryption on arrival.

Transport: MQTT topic Ptopic (TCP) or UDP broadcast to 255.255.255.255:8088.


Migration messages

Migration lets a registered entity move its credentials from one Auth to another. Two authentication variants are supported: signature-based (using Auth certificates) and MAC-based (using distribution keys).

MIGRATION_REQ_WITH_SIGN (50) / MIGRATION_REQ_WITH_MAC (52)

Sent by the entity to initiate migration.

FieldTypeDescription
entityNonceBuffer (ENTITY_NONCE_SIZE)Entity-generated nonce
authNonceBuffer (AUTH_NONCE_SIZE)Nonce from the target Auth's hello
senderNameUInt8-length-prefixed StringRegistered name of the migrating entity

WITH_SIGN authenticates via an Auth certificate and signature; WITH_MAC authenticates using a distribution key and MAC.

MIGRATION_RESP_WITH_SIGN (51) / MIGRATION_RESP_WITH_MAC (53)

Sent by the target Auth to confirm migration.

FieldTypeDescription
authIDUInt32ID of the responding Auth
entityNonceBufferEcho of the entity nonce from the request
authCertificateX.509 certificate (WITH_SIGN)Auth's certificate for signature verification
encryptedNewDistributionKeyBuffer (WITH_MAC)New distribution key encrypted for the entity

Add-reader messages (file sharing)

These messages support the file-sharing use case, allowing an entity (a writer) to register additional readers that may decrypt shared content.

ADD_READER_REQ_IN_PUB_ENC (60) / ADD_READER_REQ (62)

Entity requests that a new reader be granted access to shared content. Fields mirror SESSION_KEY_REQ_IN_PUB_ENC / SESSION_KEY_REQ: entity nonce, auth nonce, number of keys, sender name, purpose JSON, and optional DH parameter.

IN_PUB_ENC encrypts the request with Auth's public key; the plain variant uses the distribution key.

ADD_READER_RESP_WITH_DIST_KEY (61) / ADD_READER_RESP (63)

Auth confirms that the reader has been added and returns session keys. Fields mirror SESSION_KEY_RESP_WITH_DIST_KEY / SESSION_KEY_RESP.


Delegated access messages

Delegated access allows an entity to act on behalf of another entity or group, typically to access resources it would not directly be permitted to access.

DELEGATED_ACCESS_REQ_IN_PUB_ENC (70) / DELEGATED_ACCESS_REQ (72)

Entity requests delegated session keys. Fields are structurally identical to the session key request messages: entity nonce, auth nonce, number of keys, sender name, purpose, and optional DH parameter.

DELEGATED_ACCESS_RESP_WITH_DIST_KEY (71) / DELEGATED_ACCESS_RESP (73)

Auth returns session keys for delegated access, with or without a distribution key.


Privilege messages

Privilege messages establish an entity's authority to grant delegated access to others. An entity must first prove it holds the privilege before it can issue delegation.

PRIVILEGED_REQ_IN_PUB_ENC (80) / PRIVILEGED_REQ (82)

Entity requests a privilege credential that it can later present when issuing delegated access. Payload structure is identical to the session key request messages.

PRIVILEGED_RESP_WITH_DIST_KEY (81) / PRIVILEGED_RESP (83)

Auth responds with the privilege credential (encoded as session keys), optionally including the distribution key.