当我运行命令
btc_address_dump "0x0000000000000000000000000000000000000000000000000000000000000001"
时,输出的公钥是0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
,然后当我运行命令btc_address_dump "0x0000000000000000000000000000000000000000000000000000000000000002"
时,输出的公钥是04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a
,但是当我使用上面的每个私钥来测试下面的python3脚本时私钥的输出
0x0000000000000000000000000000000000000000000000000000000000000001
= 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
那么我输入私钥0x0000000000000000000000000000000000000000000000000000000000000002
时从脚本中得到的公钥是043cea112c8dbb47dbffdd56023c41ccf7f1f5a0ef8786d3b0f3f01871a6c8d557d0f0a997646d7e87ba593fed9f320dd1739c722c7b357d6586e9fb73f578c0e0
我使用的脚本如下:
# Define the elliptic curve parameters
p = 2**256 - 2**32 - 977
a = 0
b = 7
Gx = 55066263022277343669578718895168534326250603453777594175500187360389116729240
Gy = 32670510020758816978083085130507043184471273380659243275938904335757337482424
# Define the private key
private_key = 0x0000000000000000000000000000000000000000000000000000000000000002
# Convert the private key to decimal
private_key_decimal = int(private_key)
# Perform elliptic curve multiplication
Qx = Gx
Qy = Gy
for bit in bin(private_key_decimal)[3:]:
Qx = (Qx**2 - Qy**2) % p
Qy = (2*Qx*Qy) % p
if bit == '1':
Qx = (Qx*Gx - Qy*Gy) % p
Qy = (Qx*Gy + Qy*Gx) % p
# Convert the x and y coordinates to hexadecimal
public_key_hex = '04' + format(Qx, '064x') + format(Qy, '064x')
# Print the uncompressed public key
print("Uncompressed Public Key:", public_key_hex)
我的问题是为什么脚本会输出错误的公钥
0x0000000000000000000000000000000000000000000000000000000000000002
以下脚本产生预期结果:
import collections
EllipticCurve = collections.namedtuple('EllipticCurve', 'name p a b g n h')
curve = EllipticCurve(
'secp256k1',
# Field characteristic.
p=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,
# Curve coefficients.
a=0,
b=7,
# Base point.
g=(0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,
0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8),
# Subgroup order.
n=0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141,
# Subgroup cofactor.
h=1,
)
# Modular arithmetic ##########################################################
def inverse_mod(k, p):
"""Returns the inverse of k modulo p.
This function returns the only integer x such that (x * k) % p == 1.
k must be non-zero and p must be a prime.
"""
if k == 0:
raise ZeroDivisionError('division by zero')
if k < 0:
# k ** -1 = p - (-k) ** -1 (mod p)
return p - inverse_mod(-k, p)
# Extended Euclidean algorithm.
s, old_s = 0, 1
t, old_t = 1, 0
r, old_r = p, k
while r != 0:
quotient = old_r // r
old_r, r = r, old_r - quotient * r
old_s, s = s, old_s - quotient * s
old_t, t = t, old_t - quotient * t
gcd, x, y = old_r, old_s, old_t
assert gcd == 1
assert (k * x) % p == 1
return x % p
# Functions that work on curve points #########################################
def is_on_curve(point):
"""Returns True if the given point lies on the elliptic curve."""
if point is None:
# None represents the point at infinity.
return True
x, y = point
return (y * y - x * x * x - curve.a * x - curve.b) % curve.p == 0
def point_neg(point):
"""Returns -point."""
assert is_on_curve(point)
if point is None:
# -0 = 0
return None
x, y = point
result = (x, -y % curve.p)
assert is_on_curve(result)
return result
def point_add(point1, point2):
"""Returns the result of point1 + point2 according to the group law."""
assert is_on_curve(point1)
assert is_on_curve(point2)
if point1 is None:
# 0 + point2 = point2
return point2
if point2 is None:
# point1 + 0 = point1
return point1
x1, y1 = point1
x2, y2 = point2
if x1 == x2 and y1 != y2:
# point1 + (-point1) = 0
return None
if x1 == x2:
# This is the case point1 == point2.
m = (3 * x1 * x1 + curve.a) * inverse_mod(2 * y1, curve.p)
else:
# This is the case point1 != point2.
m = (y1 - y2) * inverse_mod(x1 - x2, curve.p)
x3 = m * m - x1 - x2
y3 = y1 + m * (x3 - x1)
result = (x3 % curve.p,
-y3 % curve.p)
assert is_on_curve(result)
return result
def scalar_mult(k, point):
"""Returns k * point computed using the double and point_add algorithm."""
assert is_on_curve(point)
if k % curve.n == 0 or point is None:
return None
if k < 0:
# k * point = -k * (-point)
return scalar_mult(-k, point_neg(point))
result = None
addend = point
while k:
if k & 1:
# Add.
result = point_add(result, addend)
# Double.
addend = point_add(addend, addend)
k >>= 1
assert is_on_curve(result)
return result
#######################################################
private_key = 0x0000000000000000000000000000000000000000000000000000000000000001
public_key = scalar_mult(private_key, curve.g)
print('private key:')
print(hex(private_key))
print('public key:')
print(hex(public_key[0]), hex(public_key[1]))
print('---')
private_key = 0x0000000000000000000000000000000000000000000000000000000000000002
public_key = scalar_mult(private_key, curve.g)
print('private key:')
print(hex(private_key))
print('public key:')
print(hex(public_key[0]), hex(public_key[1]))
运行脚本会产生:
private key:
0x1
public key:
0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
---
private key:
0x2
public key:
0xc6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 0x1ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a
参考资料:
https://andrea.corbellini.name/2015/05/30/elliptic-curve-cryptography-ecdh-and-ecdsa/
https://github.com/andreacorbellini/ecc/blob/master/scripts/ecdsa.py