EIP-7951 secp256r1 signature verification precompile (Precompile for secp256r1 Curve Support)
Final · EVM & execution · EIP status Final · created 2025-05-27
Adds P256VERIFY, a precompile at address 0x100 that verifies digital signatures on the secp256r1 (P-256) curve used by smartphone secure chips and WebAuthn devices. It is a specification that fixes the security flaws of RIP-7212, which is deployed on L2s.
Why it is needed
Today the only signature Ethereum can verify natively is on the secp256k1 curve. However, modern security hardware such as the iPhone Secure Enclave (Apple Secure Enclave), Android Keystore, and FIDO2/WebAuthn devices that log in with fingerprint or face recognition mostly create keys and sign with a different curve, secp256r1 (P-256). Verifying these signatures on Ethereum is currently prohibitively expensive or practically impossible. Several L2s already provide this feature through a specification called RIP-7212, but two critical security flaws that could lead to consensus failures were found in it. This EIP is a specification that keeps the same interface as RIP-7212 while fixing the flaws, and it enables account abstraction uses such as wallets that sign directly with a key built into the device, and multi-factor authentication.
What changes
Today
- Ethereum L1 provides only secp256k1 signature verification (ECRECOVER) natively.
- Verifying secp256r1 signatures from secure chips and WebAuthn devices on chain is prohibitively expensive or practically impossible.
- RIP-7212, used by several L2s, has security flaws such as a missing point-at-infinity check.
After EIP-7951
- The P256VERIFY precompile at address 0x100 verifies a secp256r1 signature for 6900 gas.
- Account abstraction patterns that use device-built-in keys and biometric authentication become possible.
- A point-at-infinity check and a mod n comparison are added, fixing the flaws of RIP-7212.
Who is affected
- Wallet & app developers: Signatures from device-built-in keys used with fingerprint or face recognition can be verified on chain for 6900 gas, which makes passkey-based wallets and account abstraction easier to build.
- Users: Wallets become possible that let users use an account through familiar means such as a smartphone secure chip and biometric authentication instead of a seed phrase.
- Client teams: The precompile must be implemented at address 0x100, and the specification must be followed exactly, including the five input validations and point-at-infinity handling.
- L2: The interface is the same as RIP-7212, so existing contract bytecode works as is, but the gas cost is 6900 instead of 3450.
In depth
Precompile address and gas cost
This adds the P256VERIFY precompile at address 0x100 with a gas cost of 6900. The value was first set by benchmarking against the existing ECRECOVER precompile (3000 gas), but actual R1 verification turned out to be considerably slower than ECRECOVER, so it was raised to 6900 gas. This cost differs from RIP-7212 (3450 gas), so gas compatibility with L2s is not preserved, but it is closer to real implementation benchmarks. The precompile must also never revert under any circumstances: if the input is malformed or verification fails, it must consume the same amount of gas as on success and return empty output.
Input/output format and encoding
The input is exactly 160 bytes: the message hash h, the signature components r and s, and the public key x-coordinate qx and y-coordinate qy, concatenated at 32 bytes each. All values are big-endian encodings of unsigned integers. Field elements must be less than the field modulus p, and scalars do not need to be less than or equal to the subgroup order n. A point on the curve is represented as 64 bytes formed by concatenating the x and y coordinates. Since (0, 0) is not a point on the secp256r1 curve, 64 zero bytes are conventionally used as the encoding of the point at infinity. The output is 32 bytes (0x00...01) if the signature is valid and 0 bytes (empty output) if it fails.
Five input validations
The precompile must perform all of the following checks and return empty output if any of them fails: 1) the input length is exactly 160 bytes, 2) r and s both satisfy 0 < r < n and 0 < s < n, 3) qx and qy both satisfy 0 ≤ qx < p and 0 ≤ qy < p, 4) the point (qx, qy) satisfies the curve equation qy^2 ≡ qx^3 + a*qx + b (mod p), 5) the point (qx, qy) is not the point at infinity (0, 0). It must also return empty output (failure) for inputs that cannot be a valid field element or point encoding.
Verification algorithm
If input validation passes, ECDSA verification is performed. First compute s1 = s^(-1) (mod n) and recover the random point used when signing as R' = (h * s1) * G + (r * s1) * (qx, qy). If R' is the point at infinity, verification fails. Take the x-coordinate r' of R', and if r' ≡ r (mod n), the signature is valid and the 32-byte value 1 is returned; otherwise empty output is returned. The comparison is done modulo n rather than as simple equality (r' == r) so that the case where the x-coordinate of R' exceeds the curve order n is handled according to the ECDSA standard.
Fixing RIP-7212 security flaws and compatibility
This EIP fixes two critical vulnerabilities in RIP-7212. First, RIP-7212 did not check whether the recovered point R' is the point at infinity. In that case the verification result could depend on how the underlying implementation handles the point at infinity, which creates nondeterministic behavior and can lead to consensus failure. Second, the comparison was corrected from r' == r to r' ≡ r (mod n). The interface is the same as RIP-7212: the same address (0x100), the same input format (160 bytes), the same output format (32 bytes), and the same return values. Only the gas cost differs, going from 3450 to 6900. The security fixes affect only edge cases that should have failed verification in the first place, so they are transparent to correctly implemented existing callers and do not break existing valid use cases.
Why verification instead of recovery
Instead of recovering the public key from the signature as ECRECOVER does, this design verifies the signature directly. Most hardware and software secp256r1 implementations verify signatures directly, the NIST FIPS 186-5 standard specifies verification rather than recovery, verification is more efficient than recovery on this curve, and existing hardware implementations provide a verification interface. Callers must therefore include the public key coordinates qx and qy in the input.
Security considerations and status
secp256r1 provides a security level of about 128 bits, equivalent to secp256k1, which Ethereum already uses. It is standardized in NIST SP 800-186, has undergone extensive cryptographic analysis, and has been deployed on several L2s in the form of RIP-7212. However, under NIST FIPS 186-5, secp256r1 ECDSA signatures are not required to be non-malleable, so applications that need non-malleability must implement additional checks at the application layer. The EIP states explicitly that the precompile does not need to perform all operations with constant-time algorithms. The source status is Final, and it was discussed at 08.29 AMA #14 with no decision.