Add functionality to efficiently perform ECDSA signature verification over the secp256r1 elliptic curve (also known as P-256 or prime256v1). This precompile enables native support for signatures generated by modern secure hardware including Apple Secure Enclave, Android Keystore, and FIDO2/WebAuthn devices.
This specification addresses critical security issues discovered in RIP-7212 while maintaining full interface compatibility with existing Layer 2 implementations.
The secp256r1 elliptic curve is a NIST-standardized curve widely supported in modern secure hardware and authentication systems. Adding native support for secp256r1 signature verification to Ethereum enables several important use cases that are currently impossible or prohibitively expensive.
Modern secure hardware devices, including Apple Secure Enclave, Android Keystore, HSMs, TEEs, and FIDO2/WebAuthn authenticators, use secp256r1 for key storage and signing operations. Native secp256r1 support enables sophisticated account abstraction patterns like device-native signing, multi-factor authentication, and simplified key management - ultimately reducing friction for mainstream adoption through familiar authentication flows.
The secp256r1 curve is already widely supported across blockchain networks and protocols, including Layer 2 networks, enterprise blockchains, and interoperability protocols. This broad compatibility enables seamless integration with existing infrastructure while maintaining security through hardware-backed signing capabilities.
This EIP supersedes RIP-7212 by implementing the same functionality with the same interface, but without the vulnerability.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.
We introduce P256VERIFY
a precompile at the address 0x100
which performs ECDSA signature verification over the secp256r1 curve with a gas cost of 3450
gas
The secp256r1 curve is fully defined by the following set of parameters:
Base field modulus = p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff
Curve equation: y^2 = x^3 + ax + b (mod p)
Curve coefficient a = 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc
Curve coefficient b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b
Base point G:
Gx = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296
Gy = 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5
Subgroup order = n = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
Cofactor = h = 0x1
These parameters are standardized by NIST in SP 800-186^1.
The field Fp is defined as the finite field of size p
with elements represented as integers between 0 and p-1 (both inclusive).
The group G is defined as a set of Fp pairs (points) (x,y)
such that either (x,y)
is (0,0)
(representing the point at infinity) or x,y
satisfy the curve equation y^2 = x^3 + ax + b (mod p)
.
A base field element (Fp) is encoded as 32
bytes by performing BigEndian encoding of the corresponding (unsigned) integer. The corresponding integer must be less than the field modulus p
.
Points in G are encoded as byte concatenation of the respective encodings of the x
and y
coordinates. Total encoding length for a G point is thus 64
bytes.
For secp256r1, the point with coordinates (0, 0)
(zeroes in Fp) is not on the curve, so a sequence of 64
zero bytes is used by convention to encode the point of infinity.
A scalar is encoded as 32
bytes by performing BigEndian encoding of the corresponding (unsigned) integer. The corresponding integer is not required to be less than or equal to the subgroup order n
.
On inputs that cannot be valid encodings of field elements or points, the precompile must return `` (failure).
P256VERIFY
OperationP256VERIFY
call expects 160
bytes as input that is interpreted as byte concatenation of:
32
bytes: message hash h
32
bytes: signature component r
32
bytes: signature component s
32
bytes: public key x-coordinate qx
32
bytes: public key y-coordinate qy
Output is 32
bytes on successful verification and 0
bytes on failure:
0x0000000000000000000000000000000000000000000000000000000000000001
for valid signaturesThe precompile MUST perform the following validation checks and return `` (failure) if any check fails:
160
bytesr
and s
MUST satisfy 0 < r < n
and 0 < s < n
qx
and qy
MUST satisfy 0 ≤ qx < p
and 0 ≤ qy < p
(qx, qy)
MUST satisfy the curve equation qy^2 ≡ qx^3 + a*qx + b (mod p)
(qx, qy)
MUST NOT be the point at infinity (represented as (0, 0)
)The verification algorithm follows these steps:
# Input validation (as specified above)
if input_length != 160:
return
if not (0 < r < n and 0 < s < n):
return
if not (0 ≤ qx < p and 0 ≤ qy < p):
return
if qy^2 ≢ qx^3 + a*qx + b (mod p):
return
if (qx, qy) == (0, 0):
return
# Signature verification
s1 = s^(-1) (mod n)
# Recover the random point used during signing
R' = (h * s1) * G + (r * s1) * (qx, qy)
# Check for point at infinity
if R' is the point at infinity:
return
# Extract x-coordinate from r
r' = R'.x
# Compare with modular reduction
if r' ≡ r (mod n):
return 0x0000000000000000000000000000000000000000000000000000000000000001
else:
return
P256VERIFY
operation3450
gas
This cost is based on benchmarking against the existing ECRECOVER
precompile (3000
gas). Secp256r1 verification is approximately 15% more expensive than secp256k1 recovery, making 3450
gas appropriate for similar performance characteristics.
The precompile MUST NOT revert under any circumstances. Invalid inputs or verification failures MUST return `` and consume the same amount of gas had verification succeeded.
This specification addresses two critical vulnerabilities in RIP-7212:
Point-at-infinity check: The original RIP-7212 failed to check if the recovered point R' is the point at infinity. This could lead to non-deterministic behavior where the verification result depends on the underlying implementation's handling of infinity points, potentially causing consensus failures.
Modular comparison: The original comparison r' == r
should be r' ≡ r (mod n)
to handle cases where the x-coordinate of R' exceeds the curve order n. This ensures mathematically correct verification according to ECDSA standards.
This specification uses signature verification rather than public key recovery (like ECRECOVER
) because:
The 3450 gas cost maintains consistency with RIP-7212 implementations and reflects the computational cost relative to existing precompiles. Benchmarking shows secp256r1 verification is approximately 15% more expensive than secp256k1 operations, justifying the cost relative to ECRECOVER
.
This EIP maintains full interface compatibility with RIP-7212 implementations deployed on Layer 2 networks. The same contract bytecode that works with RIP-7212 will work with this specification.
The security fixes are transparent to correctly implemented callers - they only affect edge cases that should have failed verification anyway. No existing valid use cases are broken.
The precompile maintains the exact same interface as RIP-7212 to ensure compatibility with existing Layer 2 deployments:
0x100
A set of test vectors for verifying implementations is located in a separate file.
A reference implementation is not supplied due to the ubiquity of secp256r1, if however a reference is needed, the NIST specification in FIPS 186-5^2
The secp256r1 curve provides approximately 128 bits of security, equivalent to secp256k1 already in use in Ethereum. The curve parameters are standardized by NIST SP 800-186^1 and have undergone extensive cryptographic analysis by the wider cryptographic community in addition to this curve being deployed to several L2s in the form of RIP-7212.
Unlike secp256k1 ECDSA signatures, secp256r1 ECDSA signatures are not required to be non-malleable per NIST FIPS 186-5 standard ^2. Applications requiring non-malleability should implement additional checks at the application layer.
We explicitly state that this precompile IS NOT REQUIRED to perform all the operations using constant time algorithms.
Copyright and related rights waived via CC0.
{
"id": "https://doi.org/10.6028/NIST.SP.800-186",
"type": "report",
"title": "Recommendations for Discrete Logarithm-based Cryptography: Elliptic Curve Domain Parameters",
"author": [
{ "given": "Lily", "family": "Chen" },
{ "given": "Dustin", "family": "Moody" },
{ "given": "Andrew", "family": "Regenscheid" },
{ "given": "Karen", "family": "Randall" },
{ "given": "Angela", "family": "Robinson" }
],
"issued": {
"date-parts": [[2023, 2, 3]]
},
"publisher": "National Institute of Standards and Technology",
"publisher-place": "Gaithersburg, MD",
"collection-title": "Special Publication",
"number": "800-186",
"URL": "https://doi.org/10.6028/NIST.SP.800-186",
"DOI": "10.6028/NIST.SP.800-186"
}
```
{
"id": "https://doi.org/10.6028/NIST.FIPS.186-5",
"type": "report",
"title": "Digital Signature Standard (DSS)",
"author": [
{ "literal": "National Institute of Standards and Technology" }
],
"issued": {
"date-parts": [[2023, 2, 3]]
},
"publisher": "National Institute of Standards and Technology",
"publisher-place": "Gaithersburg, MD",
"collection-title": "Federal Information Processing Standards Publication",
"number": "186-5",
"URL": "https://doi.org/10.6028/NIST.FIPS.186-5",
"DOI": "10.6028/NIST.FIPS.186-5"
}
```