Author: enze
Editor: Liz
Introduction
Recently, a serious security vulnerability (GHSA-vjh7-7g9h-fjfh) was discovered in the widely used elliptic cryptography library in the JavaScript ecosystem. Attackers can extract private keys by constructing specific inputs, thereby completely taking control of the victim's digital assets or identity credentials with only one signature.
The root cause of this vulnerability lies in the elliptic library's handling defects of non-standard inputs, leading to the potential repetition of the random number k in ECDSA signatures. Since the security of the ECDSA algorithm relies heavily on the uniqueness of k, once k is repeated, the private key can be directly derived, resulting in irreversible security risks.
This article will analyze the vulnerability principle, causes, and impacts, and provide repair recommendations to help developers reduce security risks.
Vulnerability Background
Introduction to the elliptic library
elliptic is a widely used elliptic curve cryptography library in the JavaScript ecosystem, supporting various curves (such as secp256k1, ed25519). This library is used by many cryptocurrency wallets, authentication systems, Web3 applications, and more.
Impact Scope
Affected Version: elliptic <= 6.6.0
Affected Curves: secp256k1, ed25519, etc.
Affected Scenarios: All applications that accept external input for ECDSA signatures (especially systems that accept external input for signing)
If an application relies on elliptic for ECDSA signatures and allows users to provide unfiltered messages as signing content, it is highly likely to be affected by this vulnerability.
Vulnerability Principle
Random number k in ECDSA signatures
Imagine you have a unique seal (private key), and each time you sign a document, you need to dip it in a unique seal (random number k). The imprint will generate two numbers r and s, which are the signature results.
There are several key points in this process:
The seal (private key) remains unchanged - representing your identity.
Each signature must use a brand-new seal (the random number k must never be reused).
Even if signing the same document, the signature results (r, s) must be different.
Anyone can verify that the imprint was made with your seal (public key verifies the signature).
But no one can derive your seal (private key) from the imprint as long as k is secure.
To ensure the security of k, ECDSA adopts the RFC 6979 specification, using a deterministic random number generator (HMAC_DRBG or HKDF) to calculate k. When generating k, the private key d and the message m are used as seeds to ensure that k is fixed under the same inputs. The calculation process is as follows:

Key Points:
1. k must be random and unique; otherwise, it can lead to private key leakage.
2. If k is the same during two signatures, the attacker can directly recover the private key d using the two signatures (r, s1) and (r, s2).
Mathematical Derivation:
Assuming the user signed two different messages m1 and m2, but the random number k was accidentally the same, the signature results would be as follows:

The attacker can compute the difference between s1 and s2:

Since m1, m2, s1, and s2 are all known, the attacker can derive k:

Then, substitute k into the original signature equation to solve for the private key d:

Vulnerability Analysis
The elliptic library was supposed to use HMAC_DRBG (Deterministic Random Number Generator) to ensure that k is unique for each signature. However, due to input handling errors, in certain cases, different messages may generate the same k, leading to private key leakage.
k Generation Code
In the sign() method of the elliptic library, k is generated by the HMAC_DRBG pseudorandom number generator, with the relevant code as follows:
elliptic/lib/elliptic/ec/index.js

The input parameters for HMAC_DRBG mainly include:
entropy → Here, the private key bkey is used to ensure that HMAC_DRBG has sufficient randomness.
nonce (random seed) → Derived from msg, affecting the final generated value of k.
Since HMAC_DRBG is deterministic, the same entropy and nonce will produce the same k. If the nonce is the same in different signing processes, k will also be the same, leading to private key leakage.
Cause of Vulnerability: BN conversion leads to nonce reuse
In the implementation of elliptic, the msg is converted to BN (Big Number), and then the nonce is computed by msg.toArray():

Problem Points:
msg is a BN instance, but the nonce is an array.
Different BN instances may generate the same array after conversion.
This means that the same nonce can be generated for different messages, ultimately leading to k reuse.
If k is reused across two different messages msg1 and msg2, the private key d can be recovered using the mathematical formulas mentioned above.
An attacker can construct a special msg such that its nonce is the same, leading to k reuse. By obtaining a pair of (r, s1) and (r, s2), the private key d can be recovered through mathematical calculations. More seriously, the attacker can construct such malicious msg against any known message/signature pair, meaning that if they induce the victim to sign a malicious message once, they can completely recover the private key and forge any signature.
Vulnerability Exploitation (PoC)
The elliptic library allows hexadecimal strings as one of the input types, converting the msg to a BN instance and then to an array type during signing. If two different messages generate the same array after conversion, the nonce will also be the same, ultimately leading to k reuse.
Code Example:

Run Output:

msg1 = "message" and msg2 = "-message" generate the same nonce after BN conversion (the design of elliptic accepts hexadecimal strings as one of the possible input types). Due to the same nonce, the k generated by HMAC_DRBG is also the same. From the signature results, it is evident that the r value is completely identical, which is a direct manifestation of k reuse.
Complete Attack Process:
1. Simulate the victim signing a normal message to obtain the message msg0 and signature sig0.
2. The attacker constructs a malicious message msg1 and induces the victim to sign it to obtain sig1.
3. Exploit the k reuse vulnerability to calculate k from (r, s1) and (r, s2).
4. Use k to further calculate the private key d, achieving a successful attack.
Code Example:

Run Output:

Fix Recommendations
1. Upgrade elliptic to 6.6.1 or higher; the issue has been officially fixed.
2. Avoid directly signing unverified messages, ensuring that msg is standardized.
3. Replace the possibly affected private keys.
Summary
The vulnerability in elliptic exposes the extreme sensitivity of ECDSA signatures to the random number k. Once k is reused, the private key can be directly recovered, allowing the attacker to fully control the user's assets and identity. Developers should promptly fix the vulnerability and strictly regulate input handling to ensure the security of ECDSA signatures. Finally, thanks to Rabby Wallet for providing the vulnerability information.
References
[1] https://github.com/indutny/elliptic/security/advisories/GHSA-vjh7-7g9h-fjfh
[2] https://paulmillr.com/posts/deterministic-signatures
