Source: p256.zig • p256.wasm.tsTests: p256.test.ts • p256.wasm.test.ts
Try it Live
Run P256 examples in the interactive playground
Overview
P256 (secp256r1) is a NIST-standardized elliptic curve for ECDSA signatures and ECDH key exchange, commonly used in hardware secure enclaves. Ethereum context: Not on mainnet - Used for hardware wallet integration (Secure Enclave, TPM, FIDO2) and account abstraction proposals. Some L2s exploring for native WebAuthn support. Curve: Short Weierstrass y² = x³ - 3x + b (mod p) Parameters:- Prime field:
p = 2²⁵⁶ - 2²²⁴ + 2¹⁹² + 2⁹⁶ - 1 - Curve order:
n = FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551 - Also called: secp256r1, prime256v1, NIST P-256
- Implementations: Native Zig (4KB), WASM via wasm-loader
- Operations: sign, verify, derivePublicKey, ecdh
- WebAuthn / FIDO2: Passkey authentication (YubiKey, TouchID, Windows Hello)
- iOS Secure Enclave: Hardware-backed cryptography on Apple devices
- TLS 1.3: Default elliptic curve for HTTPS
- Smart card / PIV: Government and enterprise PKI
- Android Keystore: Hardware-backed keys on Android
Quick Start
API Reference
Signing
sign(messageHash, privateKey)
Sign a 32-byte message hash with a private key using deterministic ECDSA (RFC 6979).
Parameters:
messageHash(HashType) - 32-byte hash to signprivateKey(Uint8Array) - 32-byte private key (0 < key < curve order)
P256SignatureType with components:
r(Uint8Array) - 32-byte signature components(Uint8Array) - 32-byte signature component
InvalidPrivateKeyError- Private key invalidP256Error- Signing failed
Verification
verify(signature, messageHash, publicKey)
Verify an ECDSA signature against a message hash and public key.
Parameters:
signature(P256SignatureType) - Signature with r, s componentsmessageHash(HashType) - 32-byte message hash that was signedpublicKey(Uint8Array) - 64-byte uncompressed public key (x || y coordinates)
boolean - true if signature is valid, false otherwise
Throws:
InvalidPublicKeyError- Public key wrong lengthInvalidSignatureError- Signature components wrong length
Key Exchange (ECDH)
ecdh(privateKey, publicKey)
Perform Elliptic Curve Diffie-Hellman key exchange. Computes a shared secret that both parties can derive independently.
Parameters:
privateKey(Uint8Array) - Your 32-byte private keypublicKey(Uint8Array) - Their 64-byte uncompressed public key
Uint8Array - 32-byte shared secret (x-coordinate of shared point)
Throws:
InvalidPrivateKeyError- Private key invalidInvalidPublicKeyError- Public key invalidP256Error- ECDH operation failed
Key Management
derivePublicKey(privateKey)
Derive the public key from a private key using elliptic curve point multiplication.
Parameters:
privateKey(Uint8Array) - 32-byte private key
Uint8Array - 64-byte uncompressed public key
Throws:
InvalidPrivateKeyError- Invalid private key
validatePrivateKey(privateKey)
Check if a byte array is a valid P-256 private key.
Parameters:
privateKey(Uint8Array) - Candidate private key
boolean - true if valid (32 bytes, > 0, < curve order)
validatePublicKey(publicKey)
Check if a byte array is a valid P-256 public key.
Parameters:
publicKey(Uint8Array) - Candidate public key
boolean - true if valid (64 bytes, point on curve)
Constants
Security Considerations
Critical Warnings
⚠️ NIST curve considerations: P-256 is a NIST-standardized curve. Some cryptographers prefer non-NIST curves (like Curve25519) due to transparency concerns about curve parameter selection. However, P-256 remains secure and widely used. ⚠️ Deterministic nonces: Uses RFC 6979 deterministic signatures. Never implement custom nonce generation - nonce reuse leaks the private key. ⚠️ Validate all inputs: Always validate private keys (0 < key < curve order) and public keys (valid curve point) before use. ⚠️ ECDH shared secret: The raw ECDH output should be used with a Key Derivation Function (KDF) like HKDF before using as a symmetric key. ⚠️ Use cryptographically secure random: Never useMath.random() for private key generation. Use crypto.getRandomValues().
TypeScript Implementation
The TypeScript implementation uses @noble/curves by Paul Miller:- Security audited and production-ready
- Constant-time operations to prevent timing attacks
- RFC 6979 deterministic signatures
- Validates all curve points and scalars
- ~20KB minified (tree-shakeable)
Test Vectors
NIST CAVP Test Vectors
Deterministic Signatures (RFC 6979)
ECDH Key Exchange
Implementation Details
TypeScript
Library:@noble/curves/nist by Paul Miller
- Audit status: Security audited, production-ready
- Standard: FIPS 186-4, SEC 2, RFC 6979 compliant
- Features: Constant-time operations, point validation, deterministic signing
- Size: ~20KB minified (tree-shakeable)
- Performance: Optimized for modern JavaScript engines
- 64-byte uncompressed public keys (x || y, no 0x04 prefix)
- RFC 6979 deterministic signing (no nonce reuse risk)
- ECDH returns x-coordinate only (standard practice)
Zig
Implementation: Future support usingstd.crypto.ecc.P256
- Status: Planned for FFI support
- Features: Constant-time, FIPS-compliant
WASM
P-256 operations available in WASM builds:- ReleaseSmall: Size-optimized
- ReleaseFast: Performance-optimized
WebAuthn Integration
P-256 is the default curve for WebAuthn (FIDO2) authentication:iOS Secure Enclave
P-256 is the only curve supported by Apple’s Secure Enclave:Web3 Usage
P-256 not in Ethereum core protocol (which uses secp256k1), but appears in:Account Abstraction (EIP-7212)
RIP-7212: Adds P-256 signature verification precompile at address0x100
- WebAuthn wallets: Use Face ID / Touch ID for transaction signing
- Hardware wallets: YubiKey and other FIDO2 devices
- Passkey accounts: Passwordless account abstraction
- Smart contract wallets: Secure Enclave-backed accounts
Layer 2 and Rollups
- StarkNet: Optional P-256 support for hardware wallets
- zkSync: Account abstraction with WebAuthn
- Optimism/Arbitrum: Precompile support in roadmap
Modern Web3 Use Cases
- Passkey wallets: Turnkey, Privy, Dynamic use P-256 for WebAuthn
- Mobile wallets: iOS Secure Enclave for key storage
- Enterprise: Hardware security modules (HSM) often default to P-256
- Government: PIV smart cards for identity verification
Comprehensive Comparison
For detailed technical comparison including performance benchmarks, security analysis, and use case recommendations, see: Elliptic Curve Comparison: secp256k1 vs P-256Quick Comparison
| Feature | P-256 | Secp256k1 |
|---|---|---|
| Ethereum Core | No (L2 only) | ✅ Required |
| WebAuthn | ✅ Default | Not supported |
| iOS Secure Enclave | ✅ Only curve | Not supported |
| Hardware Support | ✅ Excellent | Limited |
| Performance | Similar | Slightly faster |
- ✅ WebAuthn / FIDO2 authentication
- ✅ iOS Secure Enclave integration
- ✅ Hardware wallet support (YubiKey, TPM)
- ✅ Enterprise / government compliance (FIPS)
- ✅ Account abstraction with passkeys
- ✅ Ethereum transaction signing (required)
- ✅ Bitcoin compatibility
- ✅ EVM precompile support (
ecRecover) - ✅ Traditional EOA accounts
Technical Deep Dive
For implementation details, security considerations, and usage patterns similar to secp256k1:- Signing - ECDSA signing with RFC 6979 (deterministic nonces)
- Verification - Signature verification algorithm
- Key Derivation - Private → public key via elliptic curve multiplication
- ECDH - Diffie-Hellman key exchange (unique to P-256)
- Test Vectors - NIST CAVP test vectors
- Security - Side-channel resistance, constant-time operations
- Performance - Benchmarks vs secp256k1
- WebAuthn Integration - Face ID, Touch ID, YubiKey
Related
- Elliptic Curve Comparison - Comprehensive secp256k1 vs P-256 comparison
- Crypto: Secp256k1 - Ethereum’s ECDSA curve (with full documentation)
- Crypto: Ed25519 - Edwards curve signatures
- Crypto: X25519 - Curve25519 key exchange
- Primitives: Signature - Generic signature type
- Keccak256 - Message hashing (SHA-256 for WebAuthn)
- RIP-7212 - P-256 precompile proposal

