Examples
- Verify Signature - Verify signature with public key
- Validate Signature - Signature format validation
Secp256k1 Verification
Verify ECDSA signatures against public keys to authenticate messages. Signature verification is the cornerstone of Ethereum’s security model - every transaction must pass verification before execution.Overview
ECDSA verification confirms that a signature was created by the private key corresponding to a given public key. The verifier needs:- Signature (r, s, v) - 65 bytes total
- Message hash - 32 bytes (what was signed)
- Public key - 64 bytes uncompressed (x || y coordinates)
API
verify(signature, messageHash, publicKey)
Verify an ECDSA signature against a message hash and public key.
Parameters:
signature(BrandedSignature) - Signature with r, s, v componentsmessageHash(HashType) - 32-byte hash that was signedpublicKey(Uint8Array) - 64-byte uncompressed public key (x || y)
boolean
true- Signature is cryptographically validfalse- Signature is invalid or forged
InvalidPublicKeyError- Public key wrong length or not on curveInvalidSignatureError- Signature components wrong length
Algorithm Details
ECDSA Verification
-
Validate inputs:
- Check
1 ≤ r < nand1 ≤ s < n(signature component bounds) - Verify public key is a valid curve point (satisfies y² = x³ + 7)
- Check
-
Compute message hash scalar:
e = hash(message) mod n -
Calculate inverse:
s_inv = s^-1 mod n -
Compute point:
R = (e * s_inv) * G + (r * s_inv) * public_keyGis the generator pointpublic_keyis the signer’s public key point
-
Verify: Check if
R.x mod n == r- If equal, signature is valid
- If not equal, signature is invalid or forged
Why Verification Works
The signature was created as:s = k^-1 * (e + r * private_key) mod n
Rearranging: k = s^-1 * (e + r * private_key) mod n
Since R = k * G and public_key = private_key * G:
R.x == r.
Validation Checks
Signature Component Validation
Public Key Validation
Security Considerations
Malleability and Low-s
ECDSA signatures have inherent malleability: both (r, s) and (r, n - s) are valid for the same message and key. This can cause issues: Problem:sign() use low-s. Verification accepts only low-s.
Recovery ID (v) Not Required
Thev component is only needed for public key recovery (ecRecover). Standard verification ignores it because the public key is already provided.
ecRecover), v is critical.
Public Key Format
Secp256k1 public keys can be represented in multiple formats: Uncompressed (65 bytes):0x04 || x || y
- Standard format with 0x04 prefix
- Contains both x and y coordinates
x || y
- Tevm’s internal format (no prefix)
- Used by our verification API
0x02 || x or 0x03 || x
- Only x-coordinate + parity bit for y
- Not directly supported (must decompress first)
Test Vectors
Basic Verification
Wrong Public Key
Wrong Message
Malleated Signature
Invalid Signature Components
Performance
Verification Cost
ECDSA verification is computationally expensive:- Modular inversion -
s^-1 mod n(expensive) - Two scalar multiplications -
u1 * G + u2 * public_key - Point operations - Elliptic curve point addition
- TypeScript (@noble/curves): ~1-2ms per signature
- Zig (native): ~0.5-1ms per signature
- WASM (portable): ~2-4ms per signature
EVM Precompile
Ethereum providesecRecover precompile (address 0x01) for on-chain verification:
- Gas cost: 3000 gas
- Input: 128 bytes (hash, v, r, s)
- Output: 32 bytes (recovered address, zero-padded)
ecrecover() built-in instead of implementing verification in Solidity.
Implementation Notes
TypeScript
Uses@noble/curves/secp256k1:
- Constant-time operations (side-channel resistant)
- Validates all inputs (signature components, public keys)
- Enforces low-s malleability protection
- ~20KB minified, tree-shakeable
Zig
Custom implementation:- ⚠️ UNAUDITED - Not security reviewed
- ⚠️ NOT constant-time - Timing attack vulnerable
- Basic validation only
- Educational purposes only
Related
- Signing - Create signatures with private keys
- Recovery - Recover public key from signature
- Key Derivation - Derive public keys
- Security - Side-channel attacks and mitigations
- Usage Patterns - Transaction verification examples

