Created
February 4, 2022 18:10
-
-
Save maxgillett/d079995836eeb8830f16ccd35099f9b1 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 typing import (Tuple) # noqa: F401 | |
import numpy as np | |
from web3 import Web3 | |
from web3.auto import w3 | |
from eth_account.messages import encode_defunct, _hash_eip191_message | |
from eth_keys import keys | |
from eth_keys.backends.native.ecdsa import ( | |
ecdsa_raw_recover, | |
deterministic_generate_k, | |
) | |
from eth_keys.backends.native.jacobian import ( | |
fast_multiply, | |
inv, | |
) | |
from eth_utils import ( | |
big_endian_to_int, | |
int_to_big_endian, | |
) | |
from eth._utils.padding import ( | |
pad32, | |
pad32r, | |
) | |
import sympy | |
from sympy.core.numbers import igcdex | |
from fastecdsa.point import Point | |
from fastecdsa.curve import secp256k1 | |
from fastecdsa import keys as ecdsa_keys | |
P = 2**256 - 4294968273 | |
N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 | |
G = Point( | |
0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798, | |
0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8, | |
curve=secp256k1, | |
) | |
def encode_raw_public_key(raw_public_key: Tuple[int, int]) -> bytes: | |
left, right = raw_public_key | |
return b''.join(( | |
pad32(int_to_big_endian(left)), | |
pad32(int_to_big_endian(right)), | |
)) | |
def sqrt(n, p): | |
""" | |
Finds the minimum positive integer m such that (m*m) % p == n. | |
""" | |
return min(sympy.ntheory.residue_ntheory.sqrt_mod(n, p, all_roots=True)) | |
hex_message = '0x49e299a55346' | |
message = encode_defunct(hexstr=hex_message) | |
message_hash = _hash_eip191_message(message) | |
hex_message_hash = Web3.toHex(message_hash) | |
# Sign message using web3py API | |
private_key_bytes = b"\xb2\\}\xb3\x1f\xee\xd9\x12''\xbf\t9\xdcv\x9a\x96VK-\xe4\xc4rm\x03[6\xec\xf1\xe5\xb3d" | |
private_key = big_endian_to_int(private_key_bytes) | |
signed_message = w3.eth.account.sign_message(message, private_key=private_key) | |
sig = Web3.toBytes(signed_message.signature) | |
# Sign message using eth_keys backend | |
z = big_endian_to_int(message_hash) | |
k = deterministic_generate_k(message_hash, private_key_bytes) | |
r, y = fast_multiply((G.x, G.y), k) | |
s_raw = inv(k, N) * (z + r * big_endian_to_int(private_key_bytes)) % N | |
v = 27 + ((y % 2) ^ (0 if s_raw * 2 < N else 1)) | |
s = s_raw if s_raw * 2 < N else N - s_raw | |
#print("(r, y)", Web3.toHex(r), Web3.toHex(y)) | |
#print(v, Web3.toHex(r), Web3.toHex(s)) | |
# Extract ecrecover arguments | |
v, hex_r, hex_s = Web3.toInt(sig[-1]), Web3.toHex(sig[:32]), Web3.toHex(sig[32:64]) | |
ec_recover_args = (hex_message_hash, v, hex_r, hex_s) | |
canonical_v = v - 27 | |
r = big_endian_to_int(Web3.toBytes(hexstr=hex_r)) | |
s = big_endian_to_int(Web3.toBytes(hexstr=hex_s)) | |
vrs = (canonical_v, r, s) | |
print(ec_recover_args) | |
# Recover public key using fastecdsa library | |
pub_key = ecdsa_keys.get_public_key(private_key, secp256k1) | |
print(pub_key) | |
# Recover public key using eth_keys API | |
signature = keys.Signature(vrs=vrs) | |
public_key = signature.recover_public_key_from_msg_hash(message_hash) | |
print(public_key.to_hex()) | |
# Recover public key using Jacobian projection | |
raw_public_key_bytes = ecdsa_raw_recover(Web3.toBytes(message_hash), vrs) | |
print(Web3.toHex(raw_public_key_bytes)) | |
# Recover public key by deriving R from r | |
R_y = sqrt(r**3 + 7, P) | |
R = Point(r, R_y if v == 27 else -R_y, curve=secp256k1) | |
h_m = big_endian_to_int(message_hash) | |
x = s*R - h_m*G | |
r_inv = pow(r, N-2, N) | |
Q = r_inv * x | |
print(Web3.toHex(encode_raw_public_key((Q.x, Q.y)))) | |
## Print canonical Ethereum address | |
#address = public_key.to_canonical_address() | |
#print(Web3.toHex(address)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment