Expand description
Rust SDK for the macula 12 mesh: node keys (ML-DSA-87, and the LAMPS composite ML-DSA-87 + RSA-PSS-4096 in pq_hybrid), bindings and signed objects, and a station dialed over QUIC with a post-quantum key exchange.
Mobile (iOS/Android via UniFFI, macula-rust-ffi) is the flagship
consumer, not the ceiling: nothing below the FFI layer is mobile-specific.
Modules§
- binding
- TLS and CONNECT bindings and status statements, as macula_key_bindings and
macula-go make and check them. A binding ties a station’s TLS leaf, or a
node’s CONNECT key, to an identity key for up to 7 days; a status
statement keeps a binding in force for up to an hour. Each travels as
{tbs, signature}, the signature over its label, a zero byte and the tbs bytes; a verifier checks the signature over the bytes it received first, and only then decodes them. - cbor
- Deterministic CBOR encode/decode, byte-for-byte compatible with macula’s own wire codec.
- frame
- macula 12’s frames, as macula_frame and macula-go build and read them: the requests, replies, relay errors, publications and stream frames that carry signed objects, the control frames a pq_hybrid link neighbour-signs, the decoding rule’s payload bounds, and the length-prefixed wire codec.
- handshake
- macula 12’s post-quantum connection handshake, as macula_handshake and macula-go build and check it: the opener, challenge, CONNECT, HELLO and status frames (D16, D22), as CBOR bytes without the length prefix.
- keystore
- Overridable, per-platform secure storage for a node key.
- manifest
- Content manifests as macula 12’s macula_manifest builds them, byte for
byte: fixed-size chunks (256 KiB by default), SHA-384 hashes, a 50-byte
content id
<<2, Codec, SHA-384>>(tag 2 names SHA-384, D24; codec 0x55 a raw block, 0x56 a manifest), and a Merkle fold that pairs an odd last hash with itself. - node_
key - A macula 12 node’s keys, as macula and macula-go hold them: ML-DSA-87 in
pq_pure, and in pq_hybrid the LAMPS composite id-MLDSA87-RSA4096-PSS-SHA512
(draft-ietf-lamps-pq-composite-sigs), which signs with both halves and is
valid only when both verify. An identity key’s node_id (D5) solves the
admission puzzle; a CONNECT key is bound to it (see
crate::binding). Keys are stored in macula’s seed form, readable by their owner only (seeNodeKey::saveandNodeKey::load). - petname
- Petnames: a deterministic, human-readable label for a mesh node id — Docker’s adjective_color_animal convention with a four-digit suffix (e.g. “happy_green_rabbit_4831”) — so a person skimming a roster, transcript, or room listing can recognize and remember a specific identity without reading 64 hex characters. A pure function of the node id itself, not random per process: the same identity gets the same petname across restarts, across every tool that shows it, and on every other agent’s own roster too (everyone hashes the same public bytes). This is a companion label, never a replacement — every surface that adds one keeps the real node_id right alongside it, since only the real id is addressable.
- pool
- A macula 12 node’s set of station links, as macula’s client pool keeps them: one link to each seed station, every seed pinned by its node_id, all links of one node sharing its identity key, statement issuer, request admission, publication seq and event dedup. A link that ends is dialed again after the respawn delay and given back the node’s subscriptions and served procedures.
- profile
- The post-quantum crypto profile a node runs, the counterpart of macula’s
macula_crypto_profileand macula-go’sprofile. A realm runs one profile and every node in it is configured with that one: there is no default, no negotiation and no classical fallback. - record
- macula 12’s DHT records, as macula_record and macula-go sign and verify
them. A record is the signed object
{key, tbs, signature}under MACULA-PQ-RECORD-V1; its tbs holds type, alg, version, created_at, expires_at and payload, and subject only on a domain type (tags 0x20 to 0xFF).signrefuses a key whose purpose does not fit the type;verifyreads a record’s wire form in the design’s order and keeps its tbs bytes, soencodesends them unchanged. - seal
- End-to-end payload sealing, scheme 1 (macula 13, E2E design and amendment A1): what a node needs to seal a payload so that the stations relaying it cannot read it, the counterpart of macula’s macula_seal and macula-go’s seal. The byte-exact construction is macula’s test/vectors/E2E_SEAL_V1.md, and tests/vectors/seal/e2e_seal_v1.json holds its vectors.
- signed_
object - Signed objects, as macula_signed_object and macula-go sign and verify them:
a record, a request, a reply, a relay error, a publication, or a stream
frame. The fields gain
alg, the signer’s profile algorithm, and are encoded as tbs in the deterministic form; the signature covers the label, a zero byte, the SHA-384 of the signer’s key as carried, and tbs. AnObjectcarries its key; aHeldObjectleaves it out for a verifier that already holds it, and still signs its hash. - statement_
issuer - A client’s status statement issuer, the client side of macula’s
macula_statement_issuer (D22), as macula-go’s StatementIssuer. It holds the
identity key, the node’s CONNECT bindings with the newest status statement
for each, and the current CONNECT key. Each tick issues a statement valid
for an hour for each binding whose not_after has not passed, and hands it
to that binding’s subscribers, the links that connected with it. Every 5
days it rotates the CONNECT key: the new key’s binding and statement exist
before
StatementIssuer::connect_materialhands the key out, and the rotated-out binding keeps its statements until its not_after.connect_materialdoes work that is due itself, so a dial after missed ticks, a sleep or a clock step still carries material in force. Nothing is written to disk, so a new issuer starts with a new CONNECT key. - station_
link - A client’s link to one macula station, as macula_station_link and macula-go’s stationlink are: a QUIC connection dialed to the station its target pins, one bidirectional control stream, the connection handshake on it (v5, or v4 once after a station refuses v5), then status statements both ways and every frame of the session.
- transport
- Dialing a macula 12 station over QUIC, as macula-go’s
transportdoes.