Files
meshcore-spec/spec/06-payload-encrypted.md
T
swaitsandClaude Opus 4.6 9db901088e Add comprehensive spec audit results and pyMC_core issue reports
- CHANGELOG.md: Full audit findings organized by severity
- PYMC_CORE_ISSUES.md: 7 evidence-based bug reports for pyMC_core
  (wrong constants, broken path_len decoding, wrong TRACE hash,
  wrong SNR calculation)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Add comprehensive spec audit results and pyMC_core issue reports

- CHANGELOG.md: Full audit findings organized by severity
- PYMC_CORE_ISSUES.md: 7 evidence-based bug reports for pyMC_core
  (wrong constants, broken path_len decoding, wrong TRACE hash,
  wrong SNR calculation)
- Remove ERRATA.md: contents already covered by audit findings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 21:37:57 -06:00

3.9 KiB
Raw Blame History

MeshCore Protocol Specification

Section 6: Payload — Encrypted (REQ / RESPONSE / TXT_MSG)

Overview

The REQUEST, RESPONSE, and TXT_MSG payload types share an identical wire format. They consist of a destination hash, source hash, and an encrypt-then-MAC ciphertext blob. The three types differ only in their semantic meaning at the application layer.

Payload Types

Value Name Description
0x00 REQUEST Encrypted request (e.g., login, data query)
0x01 RESPONSE Encrypted response to a REQUEST or ANON_REQ
0x02 TXT_MSG Encrypted text message

Wire Format

 0
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| dest_hash(1)  |  src_hash(1)  |    Cipher MAC (2 bytes)       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
|              Ciphertext (N × 16 bytes, N ≥ 1)                |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Fields

Field Offset Size Type Description
dest_hash 0 PATH_HASH_SIZE (1) raw First byte of recipient's Ed25519 public key
src_hash 1 PATH_HASH_SIZE (1) raw First byte of sender's Ed25519 public key
cipher_mac 2 CIPHER_MAC_SIZE (2) raw Truncated HMAC-SHA256 over ciphertext
ciphertext 4 variable (multiple of 16) raw AES-128-ECB encrypted data

Minimum Size

  • Minimum payload: 4 + 16 = 20 bytes (dest_hash + src_hash + MAC + 1 AES block)

Encryption

The ciphertext is produced using the encrypt-then-MAC scheme described in Section 14:

  1. Compute the ECDH shared secret between sender and recipient.
  2. Encrypt the plaintext using AES-128-ECB with the first 16 bytes of the shared secret as the key. Zero-pad the final block.
  3. Compute HMAC-SHA256 over the ciphertext using the full 32-byte shared secret as the HMAC key. Truncate to 2 bytes.
  4. Prepend the 2-byte MAC to the ciphertext.

Decryption

  1. Extract dest_hash and src_hash.
  2. If dest_hash matches this node, search for peers matching src_hash.
  3. For each matching peer, compute or retrieve the shared secret.
  4. Verify the MAC: compute HMAC-SHA256 over the ciphertext portion using the full 32-byte shared secret. Compare the first 2 bytes with cipher_mac.
  5. If the MAC is valid, decrypt the ciphertext using AES-128-ECB with the first 16 bytes of the shared secret. The decrypted data may contain trailing zero bytes from padding.
  6. If no peer's MAC matches, the packet is not for this node (or the peer is unknown). The packet MAY still be forwarded.

Plaintext Format (TXT_MSG)

For TXT_MSG payloads, the decrypted plaintext has this structure:

Field Offset Size Type Description
timestamp 0 4 bytes uint32_le Message timestamp
txt_type_attempt 4 1 byte uint8 Upper 6 bits: message type, lower 2 bits: attempt (0-3)
text 5 remaining UTF-8 Message text

Plaintext Format (REQUEST / RESPONSE)

The plaintext format for REQUEST and RESPONSE is application-defined. Common patterns include:

  • REQUEST: [timestamp(4)][request_data...]
  • RESPONSE: [timestamp(4)][response_data...]

Cross-References

Reference Implementation

  • Mesh::createDatagram() in src/Mesh.cpp — Encoding
  • Mesh::onRecvPacket(), cases PAYLOAD_TYPE_REQ/RESPONSE/TXT_MSG — Decoding
  • Utils::encryptThenMAC() in src/Utils.cpp — Encryption
  • Utils::MACThenDecrypt() in src/Utils.cpp — Decryption and verification