Files
meshcore-spec/versions/v0.1.0/15-identity.md
T
swaitsandClaude Opus 4.7 f83d4088e3 spec: link corpus references to GitHub, version-aware
Every "Test vectors: \`corpus/...\`" mention in the spec is now a
markdown link pointing at the corresponding file or directory on
GitHub. Each version build resolves its links to the correct git
ref:

  - /latest/ -> https://github.com/swaits/meshcore-spec/tree/main/corpus/...
  - /v0.1.0/ -> https://github.com/swaits/meshcore-spec/tree/v0.1.0/corpus/...
  - future /vX.Y.Z/ -> /tree/vX.Y.Z/corpus/...

Two changes:

1. src/*.md (18 files): the inline-code corpus paths in each
   "Cross-References" section are now markdown links. Directories
   point at /tree/main/corpus/..., individual .json files point at
   /blob/main/corpus/.... CHANGELOG and other non-corpus main links
   are intentionally left pointing at main — the canonical history
   lives there regardless of which version you're reading.

2. justfile: `cut-version` now also runs a sed over the snapshot's
   *.md files replacing /tree/main/corpus -> /tree/<VERSION>/corpus
   and /blob/main/corpus -> /blob/<VERSION>/corpus. So a freshly-cut
   version is self-consistent.

versions/v0.1.0/* regenerated by re-running
`just cut-version v0.1.0` after the new src/ links + recipe sed
landed.

Tagging the release commit (`git tag v0.1.0`) is now REQUIRED — not
"optional" — because the rendered /v0.1.0/ pages reference
/tree/v0.1.0/corpus/... on GitHub. Without the tag the links 404.
cut-version's output now says so.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 10:35:09 -06:00

3.2 KiB

MeshCore Protocol Specification

Section 15: Identity

Overview

Every MeshCore node has an Ed25519 key pair. The 32-byte public key serves as the node's identity. Hashes used in routing are truncated prefixes of the public key. Shared secrets for encryption are computed via ECDH key exchange using X25519 (Ed25519 keys transposed to Curve25519).

Key Types

Type Size Description
Public Key 32 bytes (PUB_KEY_SIZE) Ed25519 public key
Private Key 64 bytes (PRV_KEY_SIZE) Ed25519 private key (seed + public)
Signature 64 bytes (SIGNATURE_SIZE) Ed25519 signature
Shared Secret 32 bytes (PUB_KEY_SIZE) ECDH shared secret

Hash Derivation

A node's routing hash is simply a prefix of its public key:

hash = pub_key[0..hash_size-1]

Where hash_size is 1, 2, or 3 bytes depending on the protocol version and path encoding (see Section 3).

For V1, PATH_HASH_SIZE is 1, meaning a node's hash is the first byte of its public key. This gives only 256 unique hash values, so hash collisions are common and expected. The protocol handles this by attempting decryption with all peers matching a given hash.

Hash Matching

To check if a hash matches a node's identity:

match = memcmp(hash, pub_key, hash_size) == 0

Ed25519 Signing

Used for advertisement signatures (see Section 5):

  1. Construct the message to sign (e.g., pub_key || timestamp || app_data).
  2. Sign using the Ed25519 private key.
  3. The 64-byte signature is included in the advertisement payload.

Verification:

  1. Extract the public key and signature from the payload.
  2. Reconstruct the message.
  3. Verify the signature using Ed25519 verification.
  4. Receivers MUST discard the packet if verification fails.

ECDH Key Exchange (X25519)

To compute a shared secret between two nodes:

  1. Convert the Ed25519 keys to X25519 (Curve25519) format.
  2. Perform X25519 Diffie-Hellman: shared_secret = X25519(my_private, their_public).
  3. The resulting 32-byte shared secret is used for:
    • AES-128 key: shared_secret[0..15]
    • HMAC-SHA256 key: shared_secret[0..31]

Identity Serialization

Identities can be serialized for storage:

  • Public Identity: 32 bytes (public key only)
  • Local Identity: 64 bytes (private key) + 32 bytes (public key) = 96 bytes

Hex representation uses uppercase characters with 2 hex digits per byte.

Cross-References

Reference Implementation

  • Identity class in src/Identity.h — Public key and verification
  • LocalIdentity class in src/Identity.h — Key pair, signing, ECDH
  • Identity::copyHashTo() — Hash derivation (prefix copy)
  • Identity::isHashMatch() — Hash comparison
  • LocalIdentity::calcSharedSecret() — ECDH key exchange