Skip to content

Auth.hmac has no minimum-length contract; 12-byte enforcement left to each implementation #21

@bibonix

Description

@bibonix

The `hmac` field in `auth.proto` (line 25) is declared as `bytes hmac = 3;` with the comment
"Truncated HMAC-SHA256 (12 bytes)". That length is documented but carries no proto-level enforcement
and no instruction to receivers about what to do when the field is shorter or absent.

In proto3, an absent field and an explicitly empty field both deserialize as a zero-length byte slice.
A malformed or adversarial client can send an `Auth` message with `hmac = bytes{}` — valid on
the wire — and the Node receives an empty slice. Nothing in the proto file or its comments requires
the Node to check `len(hmac) == 12` before invoking the HMAC comparison routine. Language
implementations vary: Go's `hmac.Equal` returns false on a length mismatch, but a Node that
checks `bytes.HasPrefix(expected, received)` or compares only the first `len(received)` bytes
would accept any one-byte HMAC that happens to match the leading byte of the correct tag (probability
1/256 per attempt). The proto spec's silence makes this a per-implementation lottery rather than a
protocol guarantee.

The issue is structurally identical to the `client_id` length problem in #13, but more
security-critical: `hmac` is the sole proof of PSK possession, so any comparison that does not
first assert `len(hmac) == 12` weakens authentication in proportion to the implementation's
deviation from standard constant-time equality.

Add `// Receivers must assert len(hmac) == 12 and reject the Auth before any HMAC comparison`
alongside the `hmac` field comment, or apply `(validate.rules).bytes.len = 12` via
protoc-gen-validate, matching the approach recommended for `client_id` in #13.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    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