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.
Recommended Fix
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.