Documentation
¶
Overview ¶
Package reqsig implements the canonical request-signature envelope used to prove that a request originates from a registered Pilot node, and the registry-signed verdict returned by verification endpoints.
Envelope canonical form (all fields fixed-charset so '|' can never occur inside a field):
pilot-req-v1|aaaaaaaaaaaa|ts|nnnnnnnnnnnnnnnn|hhhh…64…hhhh|audience
aaaa… 12 lowercase hex chars: 4 for the 16-bit network,
8 for the 32-bit node ID (the Pilot address, no separators —
the text address format "N:NNNN.HHHH.LLLL" contains ':' and
'.' and is deliberately NOT used here)
ts canonical decimal unix seconds (no sign, no leading zeros)
nonce 16 lowercase hex chars (8 random bytes)
body hash 64 lowercase hex chars, sha256 of the request body
audience [a-z0-9.-]{1,64}, the consuming service's identifier
The domain prefix provides domain separation: a signature over an envelope can never be confused with a protocol-internal signature (heartbeats, key exchange, badges), and signers MUST refuse to sign anything that is not a well-formed envelope naming their own address.
Freshness: verifiers reject envelopes whose timestamp is outside a skew window (DefaultMaxSkew). Nonce dedup within the window is the consuming service's responsibility; the registry echoes the nonce in its verdict so services can key a dedup cache on it.
Index ¶
- Constants
- func CheckFresh(e Envelope, now time.Time, maxSkew time.Duration) error
- func HashBody(body []byte) string
- func HashEnvelope(canonical string) string
- func NewNonce() (string, error)
- func Sign(priv ed25519.PrivateKey, e Envelope) (canonical, sigB64 string, err error)
- func SignVerdict(priv ed25519.PrivateKey, v Verdict) (canonical, sigB64 string, err error)
- type Envelope
- type Verdict
Constants ¶
const ( // Domain is the envelope domain-separation prefix. Domain = "pilot-req-v1" // DefaultMaxSkew is the default freshness window for envelope // timestamps. Deliberately generous: the fleet includes embedded // devices and NAT'd VMs with real clock skew, and replay within the // window is bounded by the consumer's nonce dedup. DefaultMaxSkew = 300 * time.Second // NonceLen is the hex length of an envelope nonce (8 random bytes). NonceLen = 16 )
const VerdictDomain = "pilot-verdict-v1"
VerdictDomain is the verdict domain-separation prefix.
Variables ¶
This section is empty.
Functions ¶
func CheckFresh ¶
CheckFresh returns an error when the envelope timestamp is outside the [now-maxSkew, now+maxSkew] window. maxSkew <= 0 selects DefaultMaxSkew.
func HashEnvelope ¶
HashEnvelope returns the canonical envelope-hash field for a canonical envelope string.
func Sign ¶
func Sign(priv ed25519.PrivateKey, e Envelope) (canonical, sigB64 string, err error)
Sign validates the envelope, builds its canonical form, and signs it. Returns the canonical string and the base64 signature.
func SignVerdict ¶
func SignVerdict(priv ed25519.PrivateKey, v Verdict) (canonical, sigB64 string, err error)
SignVerdict validates the verdict, builds its canonical form, and signs it.
Types ¶
type Envelope ¶
type Envelope struct {
Network uint16
Node uint32
Timestamp int64 // unix seconds
Nonce string // 16 lowercase hex chars
BodyHash string // 64 lowercase hex chars (sha256 of body)
Audience string // [a-z0-9.-]{1,64}
}
Envelope is a parsed request-signature envelope.
type Verdict ¶
type Verdict struct {
EnvHash string // sha256 hex of the canonical envelope
Network uint16
Node uint32
Valid bool
Online bool
NetworkMember bool
LastSeenUnix int64
KeyGeneration int64
VerifiedAt int64 // unix seconds
}
Verdict is the registry's signed answer to a verification request. It binds the verified envelope (by hash) to the registry's assessment so a consumer can cache the verdict, forward it as proof, or check it offline without trusting the transport it arrived over.
Canonical form:
pilot-verdict-v1|envhash|aaaaaaaaaaaa|v|o|m|last_seen|keygen|verified_at envhash 64 lowercase hex, sha256 of the canonical envelope string aaaa… 12 lowercase hex, the address the verdict is about v/o/m single chars '0'/'1': valid, online, network_member last_seen canonical decimal unix seconds (0 when unknown/invalid) keygen canonical decimal key generation (rotate count; 0 unknown) verified_at canonical decimal unix seconds of the verification
The verdict-issuer keyring follows the badgeverify pattern: kid→pubkey entries baked at build time, overridable via
-ldflags "-X github.com/pilot-protocol/common/reqsig.verdictKeyringB64=vfy-v1=<b64pub>"
Unknown kid or empty keyring fails closed.
func ParseVerdict ¶
ParseVerdict parses and validates a canonical verdict string.
func VerifyVerdict ¶
VerifyVerdict verifies a verdict signature using the build-embedded keyring, selecting the issuer key by kid. Fails closed on unknown kid.
func VerifyVerdictWithKey ¶
VerifyVerdictWithKey verifies a verdict signature with an explicit issuer public key (e.g. one fetched from the registry's verify-keys endpoint).