Skip to main content

Try it Live

Run Secp256k1 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.

Examples

Secp256k1 Public Key Recovery

Recover the signer’s public key from an ECDSA signature and message hash. This is the core mechanism of Ethereum’s ecRecover precompile and enables address-based authentication without storing public keys on-chain.

Overview

ECDSA signatures contain enough information to recover the signer’s public key:
  • Signature (r, s, v) - 65 bytes
  • Message hash - 32 bytes
From these, we can compute the public key without knowing the private key. This enables:
  • ecRecover precompile - On-chain signature verification (address 0x01)
  • Transaction authentication - Derive sender address from transaction signature
  • Message signing - Verify signed messages (EIP-191, EIP-712)
  • Compact storage - Store signatures instead of public keys

API

recoverPublicKey(signature, messageHash)

Recover the 64-byte public key from a signature and message hash. Parameters:
  • signature (BrandedSignature) - Signature with r, s, v components
  • messageHash (HashType) - 32-byte hash that was signed
Returns: Uint8Array - 64-byte uncompressed public key (x || y) Throws:
  • InvalidSignatureError - Invalid signature format or recovery failed
  • InvalidHashError - Hash wrong length
Example:

Algorithm Details

ECDSA Public Key Recovery

Given signature (r, s, v) and message hash e:
  1. Reconstruct R point from r:
    • r is the x-coordinate of ephemeral point R = k * G
    • Solve for y: y² = x³ + 7 mod p (curve equation)
    • Two possible y values (positive and negative)
    • Recovery ID v selects which y to use
  2. Calculate helper values:
    • r_inv = r^-1 mod n (modular inverse of r)
    • e_neg = -e mod n (negation of message hash)
  3. Recover public key:
    Where:
    • R is the reconstructed point
    • G is the generator point
    • * denotes scalar multiplication
  4. Verify recovery:
    • Check recovered key is valid curve point
    • Optionally verify signature with recovered key

Why Recovery Works

The signature was created as:
Rearranging:
Since public_key = private_key * G and R = k * G:
This matches step 3 above.

Recovery ID (v)

The recovery ID v resolves ambiguities in recovery: Two y-coordinates: For each x-coordinate r, there are two possible y-values satisfying the curve equation (y and p - y). The recovery ID selects which one. Ethereum format:
  • v = 27: Use y with even parity (y & 1 == 0)
  • v = 28: Use y with odd parity (y & 1 == 1)
Standard format:
  • v = 0: Even parity
  • v = 1: Odd parity
EIP-155 (replay protection):
  • v = chainId * 2 + 35: Even parity
  • v = chainId * 2 + 36: Odd parity
Our API accepts all formats and normalizes internally.

Ethereum Integration

ecRecover Precompile

Ethereum provides a precompiled contract at address 0x0000000000000000000000000000000000000001 for on-chain recovery: Solidity:
Gas cost: 3000 gas Example:

Transaction Sender Recovery

Every Ethereum transaction signature enables sender recovery:

EIP-191 Personal Sign

Recover signer from personal_sign messages:

EIP-712 Typed Data

Recover signer from typed structured data:

Security Considerations

Recovery Uniqueness

Critical: Recovery is only unique with the correct v value. Wrong v recovers a different (invalid) public key.
Always use the v value from the original signature.

Malleability Protection

Signature malleability affects recovery: Original signature:
Malleated signature:
Both recover different public keys. Ethereum enforces low-s to prevent this.

Invalid Signature Handling

Invalid signatures can:
  • Return incorrect public keys
  • Throw errors during recovery
  • Recover keys not on the curve
Always verify recovered keys:

Test Vectors

Basic Recovery

Recovery ID Selection

EIP-191 Personal Sign

Invalid Signature Recovery

Performance

Public key recovery is more expensive than verification:
  • Verification: Requires 2 scalar multiplications
  • Recovery: Requires 2 scalar multiplications + modular square root
Typical recovery time:
  • TypeScript (@noble/curves): ~1-2ms per signature
  • Zig (native): ~0.5-1ms per signature
  • WASM (portable): ~2-4ms per signature
  • EVM (ecRecover precompile): 3000 gas (~60µs at 50M gas/sec)
For verification-only use cases, prefer verify() with known public key over recovery.

Implementation Notes

TypeScript

Uses @noble/curves/secp256k1:
  • Implements recovery via point reconstruction
  • Handles both standard (0/1) and Ethereum (27/28) v values
  • Validates recovered keys before returning
  • Constant-time operations

Zig

Custom implementation:
  • ⚠️ UNAUDITED - Not security reviewed
  • Implements modular square root for y recovery
  • Basic validation only
  • Educational purposes only