Idea
Messages signed by the source node so receivers can verify the origin chain hasn't been tampered with. Encryption is illegal under amateur regulation; signing is fine.
Recommended shape (so the next pickup doesn't start cold)
- Algorithm: Ed25519. 32-byte pubkey, 64-byte sig, ~150 µs verify on a Pi-class device, deterministic (no per-sign entropy - important for embedded HF stations), patent-free, native in .NET 8. ECDSA needs fresh randomness per sign; RSA is too heavy; Schnorr aggregation is overkill for v1.
- Wire format: new optional
sig=, sigtime= (Unix epoch s), kid= (short key-id for rotation) headers on the ihave line. Per F4 these stay on DAPPSv1> as additive forward-compatible fields; pre-F5 receivers ignore them.
- Canonical pre-image for the signature covers id-inputs (salt + payload - already what the message-id hashes) plus
dst, ttl, originator, sigtime. Excludes optional key=value extension headers (those are operator-extensibility, not security-critical).
- Replay defence:
sigtime in the canonical bytes; receiver enforces ±7 days. Salt-based id dedup already covers exact-byte replays - sigtime makes timing-tampered ones detectable.
- Identity binding (the hard part): layered.
- Primary - a community registry (OARC could host a signed JSON file in a GitHub repo at a stable URL, daemons fetch on a slow refresh, operators submit pubkeys via PR or web form).
- Fallback - periodic key beacons broadcasting our pubkey as a special discovery-class frame; receivers cache
(callsign -> pubkey) TOFU-style.
- DNS-based binding (DKIM-style TXT records) was considered but rejected for v1 because most amateur sysops don't own DNS.
- Web-of-trust deferred indefinitely (bootstrapping problem).
- Three-tier verification:
- no
sig= → backward-compatible (per-channel RequireSignature opt-in for stricter modes)
- sig present + verifies → stamp
dapps-sig-ok=true MQTT user property + green tick on dashboard
- sig present + fails → drop, record
sig.fail event with originator and reason
- Wire impact: ~70 bytes per signed message. ~0.6 s extra at 1200 baud, ~2.3 s at 300-baud HF. Bearable; per-channel toggle for short-message chat.
Out of scope even when this is picked up
- Confidentiality (illegal anyway).
- Forward secrecy (irrelevant without confidentiality).
- Per-message ephemeral keys.
- Hardware key tokens.
Pickup signal
A real-world need: abuse case, cross-implementation interop concern, or OARC-side appetite for the registry. No need to pull forward speculatively.
Status
Design parked. The recommended shape above is documented for whoever picks this up.
Migrated from plan.md Phase F5 (design parked).
Idea
Messages signed by the source node so receivers can verify the origin chain hasn't been tampered with. Encryption is illegal under amateur regulation; signing is fine.
Recommended shape (so the next pickup doesn't start cold)
sig=,sigtime=(Unix epoch s),kid=(short key-id for rotation) headers on theihaveline. Per F4 these stay onDAPPSv1>as additive forward-compatible fields; pre-F5 receivers ignore them.dst,ttl,originator,sigtime. Excludes optionalkey=valueextension headers (those are operator-extensibility, not security-critical).sigtimein the canonical bytes; receiver enforces ±7 days. Salt-based id dedup already covers exact-byte replays -sigtimemakes timing-tampered ones detectable.(callsign -> pubkey)TOFU-style.sig=→ backward-compatible (per-channelRequireSignatureopt-in for stricter modes)dapps-sig-ok=trueMQTT user property + green tick on dashboardsig.failevent with originator and reasonOut of scope even when this is picked up
Pickup signal
A real-world need: abuse case, cross-implementation interop concern, or OARC-side appetite for the registry. No need to pull forward speculatively.
Status
Design parked. The recommended shape above is documented for whoever picks this up.
Migrated from
plan.mdPhase F5 (design parked).