# signature malleability allows replay by computing complementary ECDSA signatures without the private key The secp256k1 elliptic curve has a symmetry property: for any valid signature `(r, s, v)`, a complementary signature `(r, -s mod n, flipped_v)` is also valid for the same message. An attacker can compute this complement without the private key. If the contract uses the raw signature (rather than the message hash) as a uniqueness check, the complementary signature passes verification as "new," enabling replay. OpenZeppelin's ECDSA library enforces that `s` is in the lower half of the curve order, eliminating malleability. Since [[signature replay attacks succeed when contracts verify signatures without tracking processed message hashes]], malleability is one mechanism that enables replay. The [[ecrecover returns address zero on invalid signatures which matches uninitialized address variables creating false authorization|ecrecover address(0) bug]] is a separate failure mode where invalid signatures bypass authorization entirely. **EIP-2098 compact signatures** add a bypass vector: 64-byte encoding packs the recovery bit `v` into the high bit of `s`. Malleability checks for standard 65-byte format may not handle compact encoding, so a contract rejecting `(r, high_s, v)` in standard format may accept the equivalent compact signature. Libraries must validate both formats or reject compact signatures entirely. The attack framing: given a valid `(v, r, s)`, the attacker computes `(v', r, -s mod n)` without the private key. This complementary signature verifies to the same signer address via `ecrecover`. Any contract that stores the raw signature as the replay-prevention key will accept the complementary signature as a first-time use. **Defense checklist:** 1. Use OpenZeppelin's ECDSA library (enforces lower-s canonicalization, validates v in {27, 28}) 2. Track message hashes, not raw signatures, as uniqueness identifiers 3. Check that `ecrecover` returns a non-zero address 4. Validate both standard and EIP-2098 compact forms consistently 5. Include chain ID, contract address, and nonce in signed data --- Relevant Notes: - [[signature replay attacks succeed when contracts verify signatures without tracking processed message hashes]]: the broader replay problem - [[access control vulnerabilities are the leading cause of smart contract financial losses]]: the category this falls under - [[ecrecover returns address zero on invalid signatures which matches uninitialized address variables creating false authorization]]: another signature verification failure mode - [[ECDSA nonce reuse directly reveals the private key because two signatures sharing the same r value expose k algebraically]]: extends this: nonce reuse enables key recovery, a more severe outcome than malleability-based replay - [[cross-chain replay of signatures without chain_id binding impacts any signature scheme used across multi-chain deployments]]: sibling: cross-chain replay from missing chain_id is another replay vector alongside malleability; both are sub-patterns of the signature replay taxonomy - [[BLS signature aggregation enables rogue-key attacks where an attacker forges multi-signatures by registering a cancellation public key]]: sibling in the "valid-without-authorization" signature class; ECDSA malleability computes a complementary single-party signature from secp256k1 curve symmetry while BLS rogue-key forges a multi-party aggregate by canceling the honest key in aggregation; both produce valid-but-unauthorized signatures without private key knowledge Topics: - [[vulnerability-patterns]]