PIP | Title | Description | Author | Discussion | Status | Type | Date |
---|---|---|---|---|---|---|---|
27 |
Precompiled for secp256r1 Curve Support |
Proposal to add precompiled contract that performs signature verifications in the “secp256r1” elliptic curve. |
Ulaş Erdoğan (@ulerdogan), Doğan Alpaslan (@doganalpaslan) |
Final |
Core |
2023-10-12 |
This PIP follows the RIP-7212 proposal and brings the idea of inclusion with the RIP initiative.
This proposal creates a precompiled contract that performs signature verifications in the “secp256r1” elliptic curve by given parameters of message hash,
r
ands
components of the signature,x
andy
coordinates of the public key. So that, any EVM chain - principally Ethereum rollups - will be able to integrate this precompiled contract easily.
Polygon is one of the pioneer blockchains in the account abstraction ecosystem, so it's important to enhance chains capabilities and provide the best security, development experience, and user experience by following latest improvements.
“secp256r1” elliptic curve is a standardized curve by NIST which has the same calculations by different input parameters with “secp256k1” elliptic curve used by the “ecrecover” precompiled contract. The cost of combined attacks and the security conditions are almost the same for both curves. Adding a precompiled contract which is similar to "ecrecover" can provide signature verifications using the “secp256r1” elliptic curve in the smart contracts and multi-faceted benefits can occur. One important factor is that this curve is widely used and supported in many modern devices such as Apple’s Secure Enclave, Webauthn, Android Keychain which proves the user adoption. Additionally, the introduction of this precompiled contract could enable valuable features in the account abstraction which allows more efficient and flexible management of accounts by transaction signs in mobile devices. Most of the modern devices and applications rely on the “secp256r1” elliptic curve. The addition of this precompiled contract enables the verification of device native transaction signing mechanisms. For example:
- Apple's Secure Enclave: There is a separate “Trusted Execution Environment” in Apple hardware which can sign arbitrary messages and can only be accessed by biometric identification.
- Webauthn: Web Authentication (WebAuthn) is a web standard published by the World Wide Web Consortium (W3C). WebAuthn aims to standardize an interface for authenticating users to web-based applications and services using public-key cryptography. It is being used by almost all of the modern web browsers.
- Android Keystore: Android Keystore is an API that manages the private keys and signing methods. The private keys are not processed while using Keystore as the applications’ signing method. Also, it can be done in the “Trusted Execution Environment” in the microchip.
- Passkeys: Passkeys is utilizing FIDO Alliance and W3C standards. It replaces passwords with cryptographic key-pairs which is also can be used for the elliptic curve cryptography.
Modern devices have these signing mechanisms that are designed to be more secure and they are able to sign transaction data, but none of the current wallets are utilizing these signing mechanisms. So, these secure signing methods can be enabled by the proposed precompiled contract to initiate the transactions natively from the devices and also, can be used for the key management. This proposal aims to reach maximum security and convenience for the key management.
Polygon is compatible to follow the original RIP specification and implementations.
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.
As of
FORK_TIMESTAMP
in the integrated EVM chain, add precompiled contractP256VERIFY
for signature verifications in the “secp256r1” elliptic curve at addressPRECOMPILED_ADDRESS
in0x100
(indicates 0x00...00100).“secp256r1” is a specific elliptic curve, also known as “P-256” and “prime256v1” curves. The curve is defined with the following equation and domain parameters:
# curve: short weierstrass form y^2 ≡ x^3 + ax + b # p: curve prime field modulus 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff # a: elliptic curve short weierstrass first coefficient 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc # b: elliptic curve short weierstrass second coefficient 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b # G: base point of the subgroup (0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296, 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5) # n: subgroup order (number of points) 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 # h: cofactor of the subgroup 0x1
The signature verifying algorithm takes the signed message hash, the signature components provided by the “secp256r1” curve algorithm, and the public key derived from the signer private key. The verification can be done with the following steps:
# h (message hash) # pubKey = (public key of the signer private key) # Calculate the modular inverse of the signature proof: s1 = s^(−1) (mod n) # Recover the random point used during the signing: R' = (h * s1) * G + (r * s1) * pubKey # Take from R' its x-coordinate: r' = R'.x # Calculate the signature validation result by comparing whether: r' == r
The following requirements MUST be checked by the precompiled contract to verify signature components are valid:
- Verify that the
r
ands
values are in(0, n)
(exclusive) wheren
is the order of the subgroup.- Verify that the point formed by
(x, y)
is on the curve and that bothx
andy
are in[0, p)
(inclusive 0, exclusive p) wherep
is the prime field modulus. Note that many implementations use(0, 0)
as the reference point at infinity, which is not on the curve and should therefore be rejected.The
P256VERIFY
precompiled contract is proposed with the following input and outputs, which are big-endian values:
- Input data: 160 bytes of data including:
- 32 bytes of the signed data
hash
- 32 bytes of the
r
component of the signature- 32 bytes of the
s
component of the signature- 32 bytes of the
x
coordinate of the public key- 32 bytes of the
y
coordinate of the public key- Output data: 32 bytes of result data and error
- If the signature verification process succeeds, it returns 1 in 32 bytes format.
The use of signature verification cost by
P256VERIFY
is3450
gas. Following reasons and calculations are provided in the Rationale and Test Cases sections.
The following rationales are provided by the original RIP and also valid for the PIP scope.
“secp256r1” ECDSA signatures consist of
v
,r
, ands
components. While thev
value makes it possible to recover the public key of the signer, most signers do not generate thev
component of the signature sincer
ands
are sufficient for verification. In order to provide an exact and more compatible implementation, verification is preferred over recovery for the precompile.Existing P256 implementations verify
(x, y, r, s)
directly. We've chosen to match this style here, encoding each argument for the EVM as auint256
.This is different from the
ecrecover
precompiled address specification. The advantage is that it 1. follows the NIST specification (as defined in NIST FIPS 186-5 Digital Signature Standard (DSS)), 2. matches the rest of the (large) P256 ecosystem, and most importantly 3. allows execution clients to use existing well-vetted verifier implementations and test vectors.Another important difference is that the NIST FIPS 186-5 specification does not include a malleability check. We've matched that here in order to maximize compatibility with the large existing NIST P-256 ecosystem.
Wrapper libraries SHOULD add a malleability check by default, with functions wrapping the raw precompile call (exact NIST FIPS 186-5 spec, without malleability check) clearly identified. For example,
P256.verifySignature
andP256.verifySignatureWithoutMalleabilityCheck
. Adding the malleability check is straightforward and costs minimal gas.The
PRECOMPILED_ADDRESS
is chosen as0x100
asP256VERIFY
is the first precompiled contract presented as an RIP, and the address is the first available address in the precompiled address set that is reserved for the RIP precompiles.The gas cost is proposed by comparing the performance of the
P256VERIFY
and theECRECOVER
precompiled contract which is implemented in the EVM at0x01
address. It is seen that “secp256r1” signature verification is ~15% slower (elaborated in test cases) than “secp256k1” signature recovery, so3450
gas is proposed by comparison which causes similar “mgas/op” values in both precompiled contracts.
No additional backwards compatibility issues are found for Polygon.
No backward compatibility issues found as the precompiled contract will be added to
PRECOMPILED_ADDRESS
at the next available address in the precompiled address set.
This section includes the test cases and benchmark results for the proposed precompiled contract by go-ethereum client which are still valid cases for Polygon.
Functional tests are applied for multiple cases in the reference implementation of
P256VERIFY
precompiled contract and they succeed. Benchmark tests are also applied for bothP256VERIFY
andECRECOVER
with some pre-calculated data and signatures in the “go-ethereum”s precompile testing structure to propose a meaningful gas cost for the “secp256r1” signature verifications by the precompiled contract implemented in the reference implementation. The benchmark test results by example data in the assets can be checked:# results of geth benchmark tests of # ECRECOVER and P256VERIFY (reference implementation) # by benchstat tool goos: darwin goarch: arm64 pkg: github.com/ethereum/go-ethereum/core/vm │ compare_p256Verify │ compare_ecrecover │ │ sec/op │ sec/op │ PrecompiledP256Verify/p256Verify-Gas=3450-8 57.75µ ± 1% PrecompiledEcrecover/-Gas=3000-8 50.48µ ± 1% geomean 57.75µ 50.48µ │ compare_p256Verify │ compare_ecrecover │ │ gas/op │ gas/op │ PrecompiledP256Verify/p256Verify-Gas=3450-8 3.450k ± 0% PrecompiledEcrecover/-Gas=3000-8 3.000k ± 0% geomean 3.450k 3.000k │ compare_p256Verify │ compare_ecrecover │ │ mgas/s │ mgas/s │ PrecompiledP256Verify/p256Verify-Gas=3450-8 59.73 ± 1% PrecompiledEcrecover/-Gas=3000-8 59.42 ± 1% geomean 59.73 59.42 │ compare_p256Verify │ compare_ecrecover │ │ B/op │ B/op │ PrecompiledP256Verify/p256Verify-Gas=3450-8 1.523Ki ± 0% PrecompiledEcrecover/-Gas=3000-8 800.0 ± 0% geomean 1.523Ki 800.0 │ compare_p256Verify │ compare_ecrecover │ │ allocs/op │ allocs/op │ PrecompiledP256Verify/p256Verify-Gas=3450-8 33.00 ± 0% PrecompiledEcrecover/-Gas=3000-8 7.000 ± 0% geomean 33.00 7.000
The reference implementation can be easily adapted to Polygon codebase.
Implementation of the
P256VERIFY
precompiled contract is applied to go-ethereum client to create a reference. Also, a “secp256r1” package has already been included in the Besu Native library which is used by Besu client. Other client implementations are in the future roadmap.
No additional security issues are found for Polygon.
The changes are not directly affecting the protocol security, it is related with the applications using
P256VERIFY
for the signature verifications. The “secp256r1” curve has been using in many other protocols and services and there is not any security issues in the past.
Copyright and related rights waived via CC0, follows the original proposal RIP-7212.