SC Message Protocol
Relevant source files
The following files were used as context for generating this wiki page:
The Sovereign Communications (SC) Message Protocol defines the binary data structure for all messages transmitted across the decentralized mesh network. It is a core component of the @sc/core shared library, ensuring consistent and secure communication across all platforms (Web, Android, iOS). The protocol is designed to be compact, efficient, and secure, incorporating cryptographic signatures for authentication and providing a flexible payload for encrypted content.
This protocol is fundamental to the project's architecture, enabling features like end-to-end encryption, message routing, and deduplication. Its implementation can be found in the core/src/protocol/ directory.
Sources: CONTRIBUTING.md, IMPLEMENTATION_SUMMARY.md, README.md
Message Structure
Every message in the SC network consists of two primary parts: a fixed-size Header and a variable-length Payload. This design allows for efficient parsing and routing by network peers, as they can inspect the header without needing to decrypt or process the entire payload.
Sources: IMPLEMENTATION_SUMMARY.md, core/src/protocol/message.ts:14-22
The following diagram illustrates the high-level structure of a message.
Header Format
The message header is a fixed 109-byte structure containing metadata essential for routing, authentication, and message handling.
| Field | Size (bytes) | Data Type | Description |
|---|---|---|---|
version | 1 | UInt8 | The protocol version number. |
type | 1 | UInt8 | The type of message, corresponding to the MessageType enum. |
ttl | 1 | UInt8 | Time-To-Live. Decremented at each hop to prevent infinite routing loops. |
reserved | 1 | UInt8 | Reserved for future use. |
timestamp | 8 | BigInt64 | Unix timestamp in milliseconds when the message was created. |
senderId | 32 | Uint8Array | The sender's 32-byte Ed25519 public key for identity verification. |
signature | 65 | Uint8Array | A 65-byte compact Ed25519 signature of the message payload hash, used for authentication. |
| Total | 109 |
Sources: IMPLEMENTATION_SUMMARY.md, README.md, core/src/protocol/message.ts:15-21, 41-50
Payload
The payload follows immediately after the 109-byte header. Its length is variable and is determined by subtracting the header size from the total buffer length. The payload typically contains the actual message content, which is encrypted using XChaCha20-Poly1305 for confidentiality and integrity.
Sources: IMPLEMENTATION_SUMMARY.md, core/src/protocol/message.ts:125-126
Message Types
The type field in the header specifies the nature of the payload. The MessageType enum defines the possible values.
| Enum Value | Name | Description |
|---|---|---|
0 | TEXT | A standard text message. |
1 | FILE_METADATA | Metadata for a file transfer. |
2 | FILE_CHUNK | A chunk of a file being transferred. |
3 | VOICE | A voice message. |
4 | CONTROL | A control message for network management (e.g., heartbeats). |
5 | PEER_DISCOVERY | A message used for discovering other peers on the network. |
6 | KEY_EXCHANGE | A message used for cryptographic key exchange protocols. |
Sources: IMPLEMENTATION_SUMMARY.md, core/src/protocol/message.ts:24-32
Serialization and Deserialization
The @sc/core library provides functions to convert between the Message object and its binary representation (Uint8Array).
encodeMessage(message: Message): Uint8Array: Takes aMessageobject and serializes it into a binary buffer.decodeMessage(buffer: Uint8Array): Message: Takes a binary buffer, validates it, and parses it into aMessageobject.
Sources: core/src/protocol/message.ts:80-128
The following flowchart shows the encoding and decoding process.
Sources: core/src/protocol/message.ts:80-128
During decoding, decodeMessage first checks if the buffer is large enough to contain a header. If not, it throws a MessageValidationError.
// core/src/protocol/message.ts:111-116
export function decodeMessage(buffer: Uint8Array): Message {
if (buffer.length < HEADER_SIZE) {
throw new MessageValidationError(
`Buffer too small: ${buffer.length} bytes. Minimum: ${HEADER_SIZE} bytes`
);
}
// ...
}
Sources: core/src/protocol/message.ts:111-116
Security and Integrity
The protocol has several features to ensure message security and integrity.
Authentication
Every message is authenticated using the senderId and signature fields in the header. The senderId is the Ed25519 public key of the originator, and the signature is a compact Ed25519 signature of the payload's hash. This allows any peer to verify that the message was sent by the claimed sender and has not been tampered with.
Sources: README.md, IMPLEMENTATION_SUMMARY.md
Confidentiality
The message payload is encrypted using XChaCha20-Poly1305, an AEAD (Authenticated Encryption with Associated Data) cipher. This ensures that only the intended recipient can read the message content. Session keys are used and rotated to provide perfect forward secrecy.
Sources: README.md, IMPLEMENTATION_SUMMARY.md
Message Deduplication
The mesh networking layer uses a SHA-256 hash of a message to identify it uniquely. This hash is stored in a cache to prevent the same message from being processed or relayed multiple times, which is crucial for the efficiency of the flood routing algorithm.
Sources: IMPLEMENTATION_SUMMARY.md, README.md
Content Validation
To prevent Cross-Site Scripting (XSS) attacks, especially in the web application, all user-generated content within a message payload is sanitized before being displayed. The system is designed to use libraries like DOMPurify to strip any potentially malicious HTML.
Sources: V1_PRODUCTION_IMPLEMENTATION_PLAN.md
Core Functions and Interfaces
The primary logic for the message protocol is located in core/src/protocol/message.ts.
| Name | Type | Description |
|---|---|---|
Message | interface | Represents a complete message with a header and payload. |
MessageHeader | interface | Defines the structure of the 109-byte message header. |
MessageType | enum | Enumerates the different types of messages. |
HEADER_SIZE | const | A constant set to 109, representing the size of the header in bytes. |
encodeMessage() | function | Serializes a Message object into a Uint8Array. |
decodeMessage() | function | Parses a Uint8Array into a Message object, performing validation. |
decodeHeader() | function | A helper function to parse only the header from a buffer. |
validateHeader() | function | A helper function to validate the fields of a parsed header. |
Sources: core/src/protocol/message.ts
Conclusion
The SC Message Protocol is a robust and secure foundation for the Sovereign Communications platform. Its fixed-size header allows for efficient network operations, while its use of modern, audited cryptography (Ed25519 and XChaCha20-Poly1305) ensures strong authentication and confidentiality. The protocol's clear structure, defined message types, and serialization functions make it a reliable and essential component of the @sc/core library, enabling secure, decentralized communication across all supported platforms.