Author: enze
Editor: Liz
Introduction
Recently, a severe security vulnerability (GHSA-vjh7-7g9h-fjfh) was discovered in the widely used elliptic encryption library in the JavaScript ecosystem. An attacker can extract the private key by constructing specific inputs and signing only once, thereby completely controlling the victim's digital assets or identity credentials.
The root cause of this vulnerability lies in the elliptic library's handling defects of non-standard inputs, which may lead to repeated random numbers k in ECDSA signatures. Since the security of the ECDSA algorithm heavily relies on the uniqueness of k, once k is repeated, the private key can be directly derived, causing irreversible security risks.
This article will analyze the principles, causes, and impacts of the vulnerability, and provide fix recommendations to help developers reduce security risks.
Vulnerability Background
Introduction to the elliptic library
The elliptic library 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, etc.
Impact Scope
Affected Version: elliptic <= 6.6.0
Affected Curves: secp256k1, ed25519, etc.
Impact Scenarios: All applications that accept external input for ECDSA signing (especially systems that accept external input for signing)
If an application relies on elliptic for ECDSA signing and allows users to provide unfiltered messages as signing content, it is very likely to be affected by this vulnerability.
Vulnerability Principle
Random number k in ECDSA signatures
Imagine you have a unique seal (private key), and every time you sign a document, you need to dip it into a unique sealant (random number k). The impression generated will produce two numbers r and s, which are the signature results.
This process has several key points:
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 mark was made by your seal (public key verifies the signature).
But no one can reverse-engineer your seal (private key) from the mark, 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 compute k. When generating k, the private key d and message m are used as seeds to ensure k is fixed under the same input. The calculation process is as follows:

Key Points:
1. k must be random and unique; otherwise, it may lead to private key exposure.
2. If k is the same during two signatures, the attacker can simply recover the private key d directly from 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 is accidentally the same, then the signature results are as follows:

The attacker can calculate the difference between s1 and s2:

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

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

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

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

Problem Points:
msg is a BN instance, but 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 aforementioned mathematical formulas.
An attacker can construct special msg such that their nonce is the same, leading to k reuse. By obtaining a pair (r, s1) and (r, s2), the attacker can recover the private key d through mathematical calculations. More seriously, the attacker can construct such malicious msg against any known message/signature pair, meaning that by inducing the victim to sign a malicious message once, the attacker can completely recover the private key and forge any signature.
Vulnerability Exploitation (PoC)
The elliptic library allows the use of hexadecimal strings as one of the input types, which converts msg into a BN instance during signing, and then into an array type. If two different messages produce the same array after conversion, the nonces will also be the same, ultimately leading to k reuse.
Code Example:

Execution Output:

msg1 = "message" and msg2 = "-message", after BN conversion, generated the same nonce (elliptic's design accepts hexadecimal strings as one of the possible input types). Since the nonce is the same, the k generated by HMAC_DRBG is also the same. From the signature results, it can be seen that the r values are exactly the same, which is a direct manifestation of k reuse.
Complete Attack Process:
1. Simulate the victim signing a normal message to obtain message msg0 and signature sig0.
2. The attacker constructs a malicious message msg1 and induces the victim to sign it, obtaining sig1.
3. Exploit the k reuse vulnerability to compute k from (r, s1) and (r, s2).
4. Further calculate the private key d using k, attack successful.
Code Example:

Execution Output:

Fix Recommendations
1. Upgrade elliptic to 6.6.1+; the official has fixed this issue.
2. Avoid directly signing unverified messages, ensuring that msg is standardized.
3. Change the potentially affected private key.
Summary
This 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 vulnerabilities and strictly regulate input handling to ensure the security of ECDSA signatures. Finally, thanks to the Rabby wallet for providing vulnerability intelligence.
References
[1] https://github.com/indutny/elliptic/security/advisories/GHSA-vjh7-7g9h-fjfh
[2] https://paulmillr.com/posts/deterministic-signatures
