Skip to main content

Try it Live

Run P256 examples in the interactive playground
This page is a placeholder. All examples on this page are currently AI-generated and are not correct. This documentation will be completed in the future with accurate, tested examples.

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
Modern usage:
  • 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 sign
  • privateKey (Uint8Array) - 32-byte private key (0 < key < curve order)
Returns: P256SignatureType with components:
  • r (Uint8Array) - 32-byte signature component
  • s (Uint8Array) - 32-byte signature component
Throws:
  • InvalidPrivateKeyError - Private key invalid
  • P256Error - 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 components
  • messageHash (HashType) - 32-byte message hash that was signed
  • publicKey (Uint8Array) - 64-byte uncompressed public key (x || y coordinates)
Returns: boolean - true if signature is valid, false otherwise Throws:
  • InvalidPublicKeyError - Public key wrong length
  • InvalidSignatureError - 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 key
  • publicKey (Uint8Array) - Their 64-byte uncompressed public key
Returns: Uint8Array - 32-byte shared secret (x-coordinate of shared point) Throws:
  • InvalidPrivateKeyError - Private key invalid
  • InvalidPublicKeyError - Public key invalid
  • P256Error - 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
Returns: 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
Returns: 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
Returns: 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 use Math.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
The TypeScript API wraps @noble/curves with consistent conventions:
  • 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 using std.crypto.ecc.P256
  • Status: Planned for FFI support
  • Features: Constant-time, FIPS-compliant
Currently only available through TypeScript/WASM interface.

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 address 0x100
This enables:
  • 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-256

Quick Comparison

FeatureP-256Secp256k1
Ethereum CoreNo (L2 only)✅ Required
WebAuthn✅ DefaultNot supported
iOS Secure Enclave✅ Only curveNot supported
Hardware Support✅ ExcellentLimited
PerformanceSimilarSlightly faster
When to use P-256:
  • ✅ WebAuthn / FIDO2 authentication
  • ✅ iOS Secure Enclave integration
  • ✅ Hardware wallet support (YubiKey, TPM)
  • ✅ Enterprise / government compliance (FIPS)
  • ✅ Account abstraction with passkeys
When to use Secp256k1:
  • ✅ 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