Skip to content

[P3] Consider widening the safety number (SAS) beyond 64 bits #19

@wachtelhund

Description

@wachtelhund

Priority: P3 (Low) · Security audit finding · area: crypto / pairing UX · design discussion, not a defect

sas.FromBinding (go/internal/sas/sas.go, mirrored in web/src/pairing/sas.js) renders the Noise channel binding as a 64-bit safety number (xxxx-xxxx-xxxx-xxxx).

Why this is only "consider", not a bug

The SAS is defense-in-depth that only matters if the pairing token has already leaked. Without the token an attacker can't complete the NNpsk0 handshake at all, so there's no MITM and nothing to compare. The 64-bit comparison is the eyeball check that catches a MITM in the leaked-token case.

The concern

In a leaked-token MITM, the attacker runs two NNpsk0 handshakes (one with each side) and controls their own ephemeral on each leg. To stay invisible they need SAS(binding_client) == SAS(binding_agent). Because they can vary both legs, this is a birthday-style grind at ~2^32 work per side rather than a 2^64 second-preimage. They cannot precompute (both bindings depend on the honest parties' fresh ephemerals), so the grind must happen inside the interactive pairing window — which makes 2^32 impractical today. Still, 64 bits is on the low side versus, e.g., Signal's 60-decimal-digit safety number.

Options

  1. Document the 64-bit choice + the leaked-token-only threat in SECURITY.md and close (cheapest; arguably sufficient).
  2. Widen to 80–96 bits (5–6 groups). Note: this changes the displayed format and the testdata/ interop vectors (pair-interop.json safety_number), and both Go and JS must move in lockstep (the byte-identical invariant in CLAUDE.md).

No action taken in the audit PRs because (2) is a protocol/UX change worth a maintainer decision.

Filed from a security audit; see also the companion PRs labeled security.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3-lowSecurity audit: low prioritysecuritySecurity audit finding

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions