Skip to main content
Sigvex

Secp256k1 Signature Malleability Remediation

How to fix Secp256k1 signature malleability vulnerabilities.

Secp256k1 Signature Malleability Remediation

Overview

Related Detector: Secp256k1 Signature Malleability

ECDSA malleability allows duplicate valid signatures. The fix is to enforce low-S canonical form by rejecting signatures where s > SECP256K1_N / 2.

const SECP256K1_HALF_N: [u8; 32] = /* N/2 as big-endian bytes */;

fn is_low_s(s: &[u8]) -> bool {
    s <= &SECP256K1_HALF_N
}

require!(is_low_s(&sig[32..64]), NonCanonicalSignature);
let recovered = secp256k1_recover(msg, recovery_id, sig)?;

Alternative Mitigations

Use Message Hash as Unique ID

Instead of using the signature as a unique identifier, use the message hash:

let msg_hash = hash(message);
require!(!used_messages.contains(&msg_hash), Replayed);
used_messages.insert(msg_hash);

Common Mistakes

Mistake: Using Signature as Nonce

// WRONG: attacker can produce alternate valid signature
let sig_hash = hash(signature);
require!(!used_sigs.contains(&sig_hash), Replay);

Use the message hash, not the signature hash, for uniqueness.

References