
In-depth vulnerability analysis, mathematical foundations, historical examples, and a Google Colab demonstration
Abstract. This paper considers a class of Invalid Curve Attacks (ICA) in TLS-ECDH protocols, first systematically described in the study by Jager et al. (2015). It is shown that the lack of a check for elliptic curve point membership allows an attacker to extract the server’s private key by using specially chosen points on curves with small subgroups. The impact of this vulnerability on cryptosystems using the secp256k1 curve, including the Bitcoin ecosystem, is analyzed. Historical examples of real-world attacks on the SunEC, Bouncy Castle libraries, and hardware HSM modules are given. Practical testing scenarios are proposed in the Google Colab environment with a full set of scripts for point validation, invalid curve detection, and a conceptual demonstration of key recovery using the Chinese Remainder Theorem (CRT).
1. Introduction
The Transport Layer Security (TLS) protocol is the foundation of secure communications on the internet. One of the key mechanisms for establishing a session key in TLS is ECDH (Elliptic Curve Diffie–Hellman), which leverages the advantages of elliptic curve cryptography: smaller key sizes with comparable security. However, as research by Jager, Schwenk, & Somorovsky (2015) showed , many TLS-ECDH implementations are vulnerable to attacks based on invalid curves.
The attack consists of the server performing a scalar multiplication with its private key without verifying that the received point belongs to the given curve. The attacker can then select a point on another curve with a low subgroup order, allowing the private key to be reconstructed piecemeal using the Chinese Remainder Theorem (CRT). This vulnerability directly threatens systems that use elliptic curve cryptography without proper validation, including some components of the Bitcoin ecosystem.
In this article, we detail the mathematical underpinnings of the attack, its connection to Bitcoin’s cryptography, provide historical examples of real-world hacks, and offer a set of testing scripts in Google Colab that allow us to practically demonstrate all key aspects of the vulnerability.
2. Mathematical foundations of vulnerability
2.1 Elliptic Curves and ECDH
An elliptic curve over a finite field F p is given by the Weierstrass equation:
E: y² = x³ + a x + b (mod p), where 4a³ + 27b² ≠ 0 (mod p).
The set of points on the curve, together with the point at infinity O, forms an Abelian group. In the ECDH protocol, the parties generate private keys d A , d B and public keys Q A = d A G , Q B = d B G , where G is the base point. The shared secret is computed as S = d A Q B = d B Q A .
2.2. Invalid Curve Attack
The formulas for adding points on a curve depend only on the x , y , and parameter a , but are independent of parameter b . This means that if an attacker sends the server a point P’ that does not lie on the original curve (with parameter b ), but lies on some other curve with the same a and a different b’ , the server, without checking membership, will perform the scalar multiplication d P’ , using the same addition formulas. Mathematically, the operation is correct on the new curve, where the point P’ has order q .
If the order q contains small prime divisors q i , then by sending points with different q i , the attacker can calculate d (mod q i ) from the results of the scalar multiplication. Then, using the Chinese Remainder Theorem (CRT), the full private key d is recovered .
Key observation: The attack is possible because point addition formulas do not use the parameter b . Checking whether a point belongs to the curve ( y² ≡ x³ + a x + b ) completely prevents this attack vector.
3. Connection with Bitcoin cryptography
Bitcoin uses an elliptic curve secp256k1 given by the equation:
secp256k1 : y² = x³ + 7 (mod p),
where p = 2²⁵⁶ − 2³² − 2⁹ − 2⁸ − 2⁷ − 2⁶ − 2⁴ − 1 is a prime number, a = 0 , b = 7 . This curve is used for key generation in the ECDSA algorithm, as well as in key exchange protocols such as BIP324 (P2P encryption) and some hardware wallets.
If a node or wallet accepts an invalid public key and multiplies by the private key without verifying secp256k1 compliance, an attacker can compromise the private key. This is especially critical for hardware security modules (HSMs), where key extraction is extremely difficult, but an attack on invalid curves bypasses protection at the mathematical operations level.
It is important to emphasize that the secp256k1 curve itself is cryptographically secure; the vulnerability arises exclusively at the protocol implementation level .
4. Historical examples of real attacks
Jager et al. (2015) analyzed popular Java cryptographic libraries: Oracle SunEC and Bouncy Castle . Both libraries were found to be completely vulnerable to the invalid curve attack. The authors demonstrated that Java-based servers using TLS-ECDH can be cracked with minimal computational effort.
Subsequently, similar vulnerabilities were discovered in Utimaco hardware security modules and some cryptographic implementations for embedded systems. This confirms the global nature of the problem: even certified devices that have passed rigorous verification can be compromised due to the lack of a trivial verification of curve point membership.
In response to these findings, RFC 7748 and RFC 8446 explicitly mandate endpoint verification before performing ECDH operations. However, many legacy systems and some modern implementations still contain this vulnerability.
5. Comparison of parameters of correct and incorrect curves
| Characteristic | Correct curve (secp256k1) | Incorrect curve (attack) |
|---|---|---|
| Equation | y² = x³ + 7 (mod p) | y² = x³ + b' (mod p), b’ ≠ 7 |
| Order of group N | One large prime number | The set of small primes q i |
| Extracting the key | Calculating ECDLP (not possible) | Using CRT for d (mod q i ) |
| Protective rule | Checking the equation before multiplying | Lack of ownership verification |
6. Security methods and secure implementations
The primary and most effective defense is an explicit check for whether a point belongs to a curve before performing a scalar multiplication. For secp256k1, the check boils down to the following calculation:
y² ≡ x³ + 7 (mod p).
Additional measures include:
- Checking that a point is not an infinity point;
- Checking that the coordinates lie in the range [0, p−1] ;
- Using constant execution times to prevent side-channel attacks.
In modern implementations, such as OpenSSL 3.0, BoringSSL and libsecp256k1, validation is performed automatically. However, when using low-level libraries or writing custom code, you must explicitly enable validation.
7. Demonstration in Google Colab
Below is a complete set of scripts for testing in Google Colab. These scripts allow you to:
- Determine the parameters of the secp256k1 curve;
- Check whether a point belongs to a curve;
- Generate valid and invalid points;
- Detect invalid points and prevent attacks;
- Demonstrate conceptually key recovery using CRT on small numbers.
All scripts are written in Python and can be run in the Google Colab environment without additional configuration.📌 Script 1. Defining secp256k1 parameters and basic functions
# secp256k1 parameters
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
a = 0
b = 7
n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
Gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
def is_on_curve(x, y):
"""Checks whether a point (x, y) belongs to the secp256k1 curve."""
return (y * y - x * x * x - b) % p == 0
def point_to_hex(x, y):
"""Returns a string representation of a period in hexadecimal format."""
return f"({hex(x)}, {hex(y)})"
# Check base point G
print("Is base point G on curve?", is_on_curve(Gx, Gy)) # True
📌 Script 2. Generating a random valid point
import random
def random_valid_point():
"""Generates a random point on secp256k1."""
while True:
x = random.randint(0, p - 1)
y2 = (x * x * x + b) % p
# Check if y2 is a quadratic residue (Legendre symbol = 1)
if pow(y2, (p - 1) // 2, p) == 1:
# For p ≡ 3 mod 4, we extract the square root
y = pow(y2, (p + 1) // 4, p)
return (x, y)
# Generate and check
P = random_valid_point()
print("Generated point:", point_to_hex(P[0], P[1]))
print("On curve?", is_on_curve(P[0], P[1])) # True
📌 Script 3. Creating an invalid point and detecting it
def invalid_point_example():
"""Returns a point that is known not to belong to secp256k1."""
x = 1
y = 2
return (x, y)
invalid = invalid_point_example()
print("Invalid point:", point_to_hex(invalid[0], invalid[1]))
print("On the curve?", is_on_curve(invalid[0], invalid[1])) # False
# Safe multiplication with checking
def safe_scalar_mult(d, point):
if not is_on_curve(point[0], point[1]):
raise ValueError("Point does not belong to curve! Attack prevented.")
# There should be an implementation of scalar multiplication here
return "Multiplication performed correctly"
try:
result = safe_scalar_mult(123, invalid)
print(result)
except ValueError as e:
print("[!]", e)
📌 Script 4. Conceptual CRT Demo (Small Numbers)
# Chinese Remainder Theorem (CRT) with a Small Example
# Let d ≡ 2 (mod 3) and d ≡ 3 (mod 5). Find d (mod 15).
def crt_small(moduli, remainders):
"""Solution of a system of comparisons for two modules."""
m1, m2 = modules
r1, r2 = remainders
# Find t such that r1 + t*m1 ≡ r2 (mod m2)
t = ((r2 - r1) * pow(m1, -1, m2)) % m2
return r1 + t * m1
modulus = (3, 5)
remainders = (2, 3)
d = crt_small(moduli, remainders)
print(f"d ≡ {remainders[0]} (mod {moduli[0]}), d ≡ {remainders[1]} (mod {moduli[1]})")
print(f"Solution: d = {d} (mod {moduli[0] * moduli[1]})")
# In a real attack, the attacker collects comparisons d (mod q_i)
# for various small q_i and recovers the full d.
📌 Script 5. Complete secure ECDH implementation with validation
import hashlib
class SecureECDH:
A secure implementation of ECDH with point checking on secp256k1.
def __init__(self, private_key):
self.d = private_key
if not (1 <= self.d < n):
raise ValueError("Invalid private key")
def compute_shared_secret(self, peer_point):
x, y = peer_point
if not is_on_curve(x, y):
raise ValueError("Point does not belong to secp256k1")
# In a real implementation, a scalar multiplication is performed here
# using constant time.
# For demonstration purposes, we return a hash of the coordinates.
shared = (x * self.d) % p
return hashlib.sha256(str(shared).encode()).hexdigest()
# Example of use
alice = SecureECDH(12345)
valid_point = random_valid_point()
secret = alice.compute_shared_secret(valid_point)
print("Shared secret (hash):", secret[:16] + "...")
# Trying with an invalid point will throw an exception
try:
alice.compute_shared_secret((1, 2))
except ValueError as e:
print("[!]", e)
⚠️ Important note: The scripts above are for educational purposes only. They demonstrate mathematical principles and security methods, but are not fully functional attack tools. Using these scripts for malicious purposes is prohibited.
The study “Practical Invalid Curve Attacks on TLS-ECDH” (2015) demonstrates a critical vulnerability in TLS protocols that allows the server’s private key to be extracted if the implementation does not verify that the obtained point belongs to an elliptic curve. This cryptanalytic fact directly threatens any systems that use elliptic curve cryptography without proper validation, including the Bitcoin cryptocurrency.
The Invalid Curve Attack exploits the lack of input validation in cryptographic libraries during ECDH key exchange. The attacker sends the server a point that belongs not to a standard curve, but to a specially chosen curve with a small subgroup. Since the point addition formulas do not use the curve parameter bbb, the server performs scalar multiplication mathematically correctly, but on a vulnerable curve.[ link.springer ]
Mathematical basis of vulnerability
The ECDH protocol is based on the calculation Q = d⋅PQ = d \cdot PQ = d⋅P, where ddd is the secret key and PPP is the base point on the Weierstrass curve y2 = x3 + ax + b (mod p) y^2 = x^3 + ax + b \pmod py2 = x3 + ax + b (mod p). When calculating the sum of two points, the parameters x3x_3x3 and y3y_3y3 depend only on the coordinates of the original points and the parameter aaa, which allows an attacker to change bbb to b′b’b′. If the order of the new curve has small prime divisors qiq_iqi, an attacker can learn d(modqi)d \pmod{q_i}d(modqi) and recover the full secret key ddd using the Chinese Remainder Theorem (CRT).[ link.springer ]
Connection to Bitcoin’s Cryptography
Bitcoin uses the elliptic curve secp256k1, defined by the equation y2=x3+7(modp)y^2 = x^3+7\pmod py2=x3+7(modp), where a=0a = 0a=0 and b=7b = 7b=7. Although Bitcoin primarily uses the ECDSA digital signature algorithm, key exchange protocols (such as BIP324 for P2P encryption) and hardware wallets can use ECDH for key derivation. If a node or wallet receives an incorrect public point and multiplies it by Bitcoin’s private key without first validating it (y2≡x3+7(modp))(y^2 \equiv x^3+7\pmod p)(y2≡x3+7(modp)), the private key will be compromised.[ datatracker.ietf ]
Historical examples and archives
Researchers from Ruhr University (Tibor Jager, Jörg Schwenk, Juraj Somorovsky) discovered that Oracle’s SunEC (Java) and Bouncy Castle libraries were completely vulnerable to the attack. In practice, this meant that most Java-based servers using TLS-ECDH could be hacked with minimal computational effort. Historically, similar attacks have been used against Utimaco hardware security modules (HSMs), confirming the global nature of the problem.[ link.springer ]
Comparison of curve parameters
| Characteristic | Correct curve (secp256k1) | Incorrect curve (Attack) |
| Equation | y2=x3+7(modp)y^2 = x^3 + 7 \pmod py2=x3+7(modp) [ datatracker.ietf ] | y2=x3+b′(modp)y^2 = x^3 + b’ \pmod py2=x3+b′(modp) [ link.springer ] |
| Order of group NNN | One large prime number [ dxdt ] | The set of small primes qiq_iqi [ pdfs.semanticscholar ] |
| Extracting the key | Computing ECDLP (impossible) [ arxiv ] | Using CRT for d(modqi)d \pmod{q_i}d(modqi) [ pdfs.semanticscholar ] |
| Protective rule | Checking an equation before multiplying [ link.springer ] | No ownership check [ link.springer ] |
Implementing checks in code
To prevent attacks, it’s necessary to explicitly verify the ownership of a point. Examples in various languages demonstrating this task are provided below.
Python
python
def is_valid_secp256k1_point(x, y, p):
# Checking the equation y^2 = x^3 + 7 (mod p)
return (y**2 – x**3 – 7) % p == 0
SageMath
python
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
E = EllipticCurve(GF(p), [0, 7])
def check_point(x, y):
return E.is_on_curve(x, y)
Magma
text
F := FiniteField(p);
E := EllipticCurve([F| 0, 7]);
IsPointOnCurve := function(x, y)
return y^2 eq x^3 + 7;
end function;
PARI/GP
text
p = 2^256 – 2^32 – 977;
E = ellinit([0, 7], p);
is_on_curve(x, y) = (y^2 – x^3 – 7) % p == 0;
Conclusion
The Invalid Curve Attack is a serious threat to systems using ECDH without point ownership verification. Despite the vulnerability being discovered over a decade ago, many implementations remain unprotected. The attack is particularly dangerous for the Bitcoin ecosystem, where compromising a private key leads to the complete loss of funds.
The main conclusion: validation of the point before performing a scalar multiplication is mandatory and should be implemented at the protocol level. Developers of cryptographic libraries and applications should use only proven implementations (e.g., libsecp256k1, OpenSSL 3.0) that perform this validation automatically.
The Google Colab scripts presented in this article allow for hands-on exploration of attack and defense mechanisms, making them a useful tool for education and security audits.
Bibliography
1. Jager, T., Schwenk, J., Somorovsky, J. (2015). Practical Invalid Curve Attacks on TLS-ECDH. In: Computer Security – ESORICS 2015. Springer. DOI: 10.1007/978-3-319-24174-6_21
2. IETF RFC 7748: Elliptic Curves for Security. datatracker.ietf.org
3. IETF RFC 8446: The Transport Layer Security (TLS) Protocol Version 1.3. datatracker.ietf.org
4. Bitcoin Wiki: Secp256k1. en.bitcoin.it
5. Bernstein, D. J., Lange, T. (2017). SafeCurves: choosing safe curves for elliptic-curve cryptography. safecurves.cr.yp.to
