Skip to main content

Module binding

Module binding 

Source
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_id without 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_id under 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::Opportunisticthe 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§

CertBlsBinding
The raw contents of a parsed (not-yet-verified) binding extension.

Enums§

BindingOutcome
The result of checking a leaf certificate for a valid BLS binding, BEFORE the policy is applied.
BindingPolicy
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_OID in 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 BindingPolicy to a BindingOutcome, deciding whether the handshake may proceed.
parse_binding_extension_value
Parse a v1 extension value into its fields. Returns None for 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.