The Story Begins
Our journey starts with a mysterious number in Ethereum's design. The Ethereum Yellow Paper mentions two special values—27 and 28—derived from adding 27 to 0 and 1, respectively. But what does this number 27 signify? Let’s embark on a cryptographic investigation.
Is This a Bug?
Discussions on Stack Exchange and GitHub suggest this might be a design bug. Ethereum’s fromRpcSig function handles the value 27 as a special case, adjusting values below 27 by adding 27 to them. This accommodates both ECDSA’s original recoveryID and Ethereum’s adjusted v values. But is it truly a bug?
Digging deeper into the code, we find:
v: chainId ? recovery + (chainId * 2 + 35) : recovery + 27This reveals three key elements: the magic numbers 27 and 35, and ChainID.
ChainID’s Role
Introduced via EIP-155, ChainID prevents transaction replay attacks across different networks (e.g., Ethereum Mainnet ChainID=1 vs. Ethereum Classic ChainID=61). While NetworkID handles network-layer isolation, ChainID secures transactions.
But why 27 and 35? Tracing back to Bitcoin’s design, Electrum’s code adds 27 to recoveryID (0–3), plus 4 for compressed keys, resulting in values 27–34. Ethereum inherited this, but the rationale remained unclear.
ECDSA’s Recover Mechanism: The Real "Bug"
ECDSA (Elliptic Curve Digital Signature Algorithm) underpins FISCO BCOS, Bitcoin, and Ethereum. Its Recover algorithm is the star here:
Key Generation:
- Private key: Random
d. - Public key:
Q = d·G(G = curve base point).
- Private key: Random
Signing:
- Hash message
mtoz. - Generate random
k, compute(x, y) = k·G. - Signature:
(r = x mod n, s = k⁻¹(z + rd) mod n).
- Hash message
Verification:
- Recompute
(x, y)usingu₁·G + u₂·Qand checkr == x.
- Recompute
Recovery:
- Reconstruct
R = (x, y)fromr(multiplexcandidates). - Compute
Q = u₁·G + u₂·Rand match known public keys.
- Reconstruct
Recovery avoids storing public keys in transactions—nodes derive them from signatures, saving bandwidth.
RecoveryID Optimizations
In secp256k1 (FISCO BCOS’s curve):
- Only 2 valid
xvalues exist (randr+n) due to modulo closeness (p ≈ n). - Probability of
r+nbeing valid: ≈3.73×10⁻³⁹ (negligible).
Calculating RecoveryID:
id = y & 1(LSB ofkG’s y-coordinate).- Toggle if
s > n/2(anti-replay).
Java SDKs optimize by computing instead of searching.
Conclusion
From Ethereum’s "27" to ECDSA’s math, we’ve unraveled how blockchain leverages cryptography for efficient, secure designs. The journey underscores a core philosophy: control the signature, control the address.
FAQs
Q1: Why does Ethereum use 27 and 28?
A1: Inherited from Bitcoin, these values adjust recoveryID (0–3) to avoid ambiguity in signature encoding.
Q2: What’s the purpose of ChainID?
A2: Prevents transaction replay across chains (e.g., ETH vs. ETC) by embedding network-specific metadata.
Q3: How does ECDSA recovery save storage?
A3: Nodes recompute public keys from signatures instead of storing them, reducing transaction size.
Q4: Is recoveryID calculation always efficient?
A4: With secp256k1, yes—only 2 likely x values exist, and Java SDKs bypass traversal via formulas.
👉 Discover more about blockchain cryptography
References: Ethereum Yellow Paper, EIP-155, SEC1/SEC2 standards.