Skip to content

daimo-eth/p256-verifier

Repository files navigation

P256Verifier Solidity contract

This is currently the only audited, open source P256 verifier. It's not quite the lowest-gas implementation, but it's close. Our implementation uses no unsafe or assembly to maximize simplicity and security.

Verifying a signature costs about 330k gas. Pure function, no precomputation.

This contract matches the EIP-7212 precompile spec.

It exists at a deterministic CREATE2 address: 0xc2b78104907F722DABAc4C69f826a522B2754De4. You can use it on any EVM chain. So far, we've deployed it on Ethereum L1, OP Mainnet, Base, Arbitrum and others. You can deploy to any EVM chain using forge script.

The secp256r1 elliptic curve, aka P256, is used by security keys like Yubikey, Apple's Secure Enclave, the Android Keystore, and WebAuthn, aka passkeys. P256 verification enables secure hardware-based signing keys, great UX and passkey backup.

Our implementation was inspired by Renaud Dubois/Ledger's FCL library and blst.

Usage

Address 0xc2b78104907F722DABAc4C69f826a522B2754De4

Available on any chain. If missing, see deploy.sh.

Install with:

  • forge install daimo-eth/p256-verifier
  • add p256-verifier/=lib/p256-verifier/src/ to remappings.txt
import "p256-verifier/P256.sol";

bytes32 hash; // message hash
uint256 r, s; // signature
uint256 x, y; // public key

bool valid = P256.verifySignature(hash, r, s, x, y);

Alternately, calling P256.verifySignatureAllowMalleability ignores malleability of signatures, matching the behavior specified by the NIST standard exactly.

You can also verify WebAuthn/Passkey signatures using the WebAuthn.sol library contract.

Audits

Development

Run foundryup to ensure you have the latest foundry. Then,

git clone --recurse-submodules git@github.com:daimo-eth/p256-verifier
cd p256-verifier
forge test -vv

This runs test input and output handling as well as all applicable Wycheproof test vectors, covering a range of edge cases.

Code coverage Install the recommended VSCode extension to view line-by-line test coverage. To regenerate coverage:
forge coverage --ir-minimum --report lcov
Test vectors

To regenerate test vectors:

cd test-vectors
npm i

# Download, extract, clean test vectors
# This regenerates ../test/vectors.jsonl
npm start

# Validate that all vectors produce expected results with SubtleCrypto and noble library implementation
npm test

# Validate that all vectors also work with EIP-7212
# Test the fallback contract...
cd ..
forge test -vv

# In future, execution spec and clients can test against the same clean vectors