Expand description
Cert BLS-binding — the anti-substitution ROOT of the DIG recipient-seal family (#1204).
A DIG peer’s transport identity is peer_id = SHA-256(TLS SPKI DER) (crate::identity). The
recipient-seal family (#1075 node↔node, #1199 relay) needs to seal a payload to a peer’s BLS
G1 identity key so a misdelivery cannot be opened by the wrong node. That is only safe if
peer_id ↔ BLS_pub is cryptographically BOUND — otherwise a man-in-the-middle could advertise a
victim’s peer_id with its OWN BLS key and read the seal. This module is that binding.
§The binding
The node/relay embeds its 48-byte compressed BLS G1 public key in its mTLS leaf certificate as
a custom X.509 extension (DIG_BLS_BINDING_OID), self-attested by a 96-byte BLS G2 signature
over the leaf’s SPKI DER. Because peer_id = SHA-256(SPKI), signing the SPKI commits the
holder’s BLS key to exactly that peer_id:
- An attacker cannot present a victim’s
peer_idwithout the victim’s exact SPKI (else the hash differs) — and presenting that SPKI needs the victim’s TLS private key (rustls proves cert-key possession during the handshake). - An attacker cannot claim a victim’s
peer_idunder their OWN BLS key: the self-attestation is an AugScheme signature (which itself covers the signing pubkey) verified against the embedded pubkey over the presented SPKI, so a forged pair fails. - An attacker cannot replay the victim’s (pubkey, sig) with a different cert: the signature covers the victim’s SPKI, not the attacker’s.
§Rollout policy (capability-negotiated, fail-closed for the strict mode)
Existing peers have un-bound (no-extension) certs, so the binding is additive — the extension
is a non-critical, unknown-to-old-verifiers X.509 extension (§5.1 spirit: old readers ignore it).
Verification is governed by a LOCAL BindingPolicy (NOT wire-negotiated, so a peer cannot
downgrade it):
BindingPolicy::Off— do not verify (pre-adoption / opt-out).BindingPolicy::Opportunistic— the rollout default: verify a binding when present, reject a present-but-INVALID one, accept an ABSENT one.BindingPolicy::Required— strict: a valid binding is mandatory; ABSENT and INVALID are both rejected. A downgrade that strips the extension is therefore rejected.
Structs§
- Cert
BlsBinding - The raw contents of a parsed (not-yet-verified) binding extension.
Enums§
- Binding
Outcome - The result of checking a leaf certificate for a valid BLS binding, BEFORE the policy is applied.
- Binding
Policy - The verification stance for a peer’s cert binding — a LOCAL decision (never wire-negotiated).
Constants§
- BINDING_
VERSION_ V1 - Version byte of the binding extension value (v1). Newer writers MAY bump this; verifiers dispatch on it and MUST keep accepting every version they understand (§5.1 additive-forever).
- DIG_
BLS_ BINDING_ OID - The DIG BLS-binding X.509 extension OID (dotted-decimal arc form used by
rcgen). - DIG_
BLS_ BINDING_ OID_ STR - The
DIG_BLS_BINDING_OIDin dotted-decimal string form (for matching parsed cert extensions).
Functions§
- binding_
message - The exact byte string the BLS-G2 self-attestation covers: the domain-separation context then the leaf’s SPKI DER. Used identically when signing (attest) and verifying.
- encode_
binding_ extension_ value - Encode the v1 extension value from a BLS G1 pubkey + its G2 self-attestation signature.
- evaluate
- Apply a
BindingPolicyto aBindingOutcome, deciding whether the handshake may proceed. - parse_
binding_ extension_ value - Parse a v1 extension value into its fields. Returns
Nonefor a wrong length or an unrecognised version — an unknown version is treated as “no binding this verifier understands” (additive forward-compat), NOT as tampering. - verify_
binding_ from_ leaf_ cert - Verify the BLS binding carried by a DER-encoded leaf certificate.