Last active
October 16, 2020 18:56
-
-
Save gitzhou/c7b61732d7a0857dbaefdc1cbfc7316f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from ec_point_operation import curve, add, scalar_multiply | |
from modular_inverse import modular_multiplicative_inverse | |
from crypto import double_sha256 | |
import random | |
def hash_to_int(message: bytes) -> int: | |
"""Calculate the bitcoin double-sha256 hash of the message, return as an integer""" | |
h = double_sha256(message) | |
return int.from_bytes(h, byteorder='big') | |
def sign(private_key: int, message: bytes) -> tuple: | |
"""Create ECDSA signature (r, s)""" | |
e = hash_to_int(message) | |
r, s = 0, 0 | |
while not r or not s: | |
k = random.randrange(1, curve.n) | |
k_x, _ = scalar_multiply(k, curve.g) | |
r = k_x % curve.n | |
s = ((e + r * private_key) * modular_multiplicative_inverse(k, curve.n)) % curve.n | |
return r, s | |
def sign_recoverable(private_key: int, message: bytes) -> tuple: | |
"""Create recoverable ECDSA signature, aka compact signature, (recovery_id, r, s)""" | |
e = hash_to_int(message) | |
recovery_id, r, s = 0, 0, 0 | |
while not r or not s: | |
k = random.randrange(1, curve.n) | |
k_x, k_y = scalar_multiply(k, curve.g) | |
# r | |
r = k_x % curve.n | |
recovery_id = 0 | 2 if k_x > curve.n else 0 | k_y % 2 | |
# s | |
s = ((e + r * private_key) * modular_multiplicative_inverse(k, curve.n)) % curve.n | |
return recovery_id, r, s | |
def verify_signature(public_key: tuple, message: bytes, signature: tuple) -> bool: | |
e = hash_to_int(message) | |
r, s = signature | |
w = modular_multiplicative_inverse(s, curve.n) | |
u1 = (w * e) % curve.n | |
u2 = (w * r) % curve.n | |
x, _ = add(scalar_multiply(u1, curve.g), scalar_multiply(u2, public_key)) | |
return r == (x % curve.n) | |
if __name__ == '__main__': | |
# 私钥 | |
priv_key = 0xf97c89aaacf0cd2e47ddbacc97dae1f88bec49106ac37716c451dcdd008a4b62 | |
# 公钥 | |
pub_key = scalar_multiply(priv_key, curve.g) | |
# 要签名的消息 | |
m = '你好世界'.encode('utf-8') | |
# 签名 | |
sig_r, sig_s = sign(priv_key, m) | |
print(' r =', sig_r) | |
print(' s =', sig_s) | |
# 验证签名 (r, s) | |
print(verify_signature(pub_key, m, (sig_r, sig_s))) | |
# 验证签名 (r, -s) | |
negative_s = -sig_s % curve.n | |
print('-s =', negative_s) | |
print(verify_signature(pub_key, m, (sig_r, negative_s))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment