Skip to content

No durable guard against signing two different messages in one slot (XMSS OTS key reuse) #1203

Description

@adust09

sign() requires: "A secret key must never sign two different messages for the same slot." But nothing durable enforces this. Breaking it leaks Winternitz chain state → forgery potential. (Fork choice accepting equivocation is intended, per test_equivocation.py — this issue is about the signing side.)

Current guards are all in-memory:

How it breaks:

  1. Crash-restart mid-slot_attested_slots wiped → re-sign with a different head
  2. Clock regression (NTP step) → proposer re-signs immediately; attester after >4 slots
  3. Backup restore / two instances on one key → same as Validator dual-key separation is maintained only by convention (a same-key manifest silently reuses XMSS OTS state) #1184, one layer up

Proposed fix: persist a monotonic last_signed_slot per key; _sign_with_key refuses slot <= last_signed_slot (minimal EIP-3076 analogue). Dual instances additionally need exclusive key-store access — an operational requirement to document.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions