Verifying ECDSA Signature Components Using Mod N in Bitcoin Core
The Electronic Cash Guidelines (ECG) and the Elliptic Curve Digital Signature Algorithm (ECDSA) are two core components of the Bitcoin protocol. In this article, we will explore how Bitcoin Core verifies ECDSA signature components using Mod N.
ECDSA Signing/Verification Process
In the book “Programming Bitcoin” by Jimmy Song, it is mentioned that the ECDSA signing/verification process for a hashed message z
involves the following steps:
- Extract the public key
P
from the private keye
.
- Calculate the signature of the hash message
z
using the ECDSA algorithm:
S = r * G^x mod M
- Verify the signature by verifying that it matches the expected signature for the given public key and message hash:
V = r ^ x mod h_p
S = S ^ V mod h_s
Mod N check
To verify ECDSA signatures using Mod N, we need to define a corresponding module “M” and a base point “G” that satisfies certain properties. The key property is that the private key “e” is a modular power of the generator point “G”.
In Bitcoin Core, the private key e
is represented by the pair (d, P)
, where d
is the private key in decimal form and P
is the public key (i.e. (x, y) )
). To validate ECDSA signatures using Mod N, we need to define the modulus M
such that:
d^e ≡ 1 mod M
G^e ≡ G^x mod M
We can choose an arbitrary modulus M = p
(a prime number) and define the private exponent e
as the modular exponent of the generator point G
. The public key P
is simply the coordinates (x, y)
.
Implementation in Bitcoin Core
To implement Mod N validation in Bitcoin Core, we can use the following code snippet:
#include
// Define a structure that represents the components of an ECDSA signature
typedef struct {
uint8_t r[4];
uint8_t x;
} S;
// Function to calculate ECDSA signature and verify it using Mod N
S ecdsa_sign(const uint8_t z, const uint64_t e, const uint8_t p) {
// Extract public key components from private key
const uint32_t d = (z[0] << 24) + (z[1] << 16) + (z[2] << 8) + z[3];
S* signature = new (sizeof(S)) S;
// Calculate ECDSA signature and verify it using Mod N
S r;
for (int i = 0; i < 4; i++) {
r.r[i] = (d >> (i * 8) & 255);
}
signature->r[3] = (z[0] << 24) + (z[1] << 16) + (z[2] << 8) + z[3];
signature->x = r.x;
// Calculate G^e ≡ G^x mod M
With g;
for (int i = 0; i < 4; i++) {
g.r[i] = pow(G, r.r[i], p);
}
return signature;
}
// Function to verify ECDSA signature using Mod N
bool ecdsa_verify(const S* signature, const uint64_t e, const uint8_t z, const uint32_t p) {
// Extract public key components from private key
const uint32_t d = (z[0] << 24) + (z[1] << 16) + (z[2] << 8) + z[3];
// Compute G^e ≡ G^x mod M
S g;
for (int i = 0; i < 4; i++) {
g.r[i] = pow(G, d >> (i * 8), p);
}
// Compare the computed signature with the expected signature
uint64_t r, x;
for (int i = 0; i < 4; i++) {
r += g.r[i];
x += (z[1] << 16) + (z[2] << 8) + z[3];
}
return pow(r, e, p) == x;
}
This implementation provides a basic framework for verifying ECDSA signatures using Mod N in Bitcoin Core. Please note that this is just an example and you may need to modify the code to suit your specific requirements.
References
- “Bitcoin Programming” by Jimmy Song (2019)
- Bitcoin Protocol Specification (Section 5.1.8)