Skip to content

Instantly share code, notes, and snippets.

@alpinevm
Last active October 21, 2024 20:43
Show Gist options
  • Select an option

  • Save alpinevm/2329083aa44258fb6c96f1a86ca2001c to your computer and use it in GitHub Desktop.

Select an option

Save alpinevm/2329083aa44258fb6c96f1a86ca2001c to your computer and use it in GitHub Desktop.
Generate arbitrary ECDSA signature + hash pairs given a public key
# Author: Alpine, @alpinevm
# python3 -m pip install eth_account ecdsa
# Inspired by: https://yondon.blog/2019/01/01/how-not-to-use-ecdsa/
import random
from eth_account import Account
from ecdsa import SECP256k1, VerifyingKey
from ecdsa.util import number_to_string
def vrs_to_signature_bytes(v, r, s):
r_bytes = r if isinstance(r, bytes) else bytes.fromhex(r[2:])
s_bytes = s if isinstance(s, bytes) else bytes.fromhex(s[2:])
v_byte = v.to_bytes(1, 'big')
signature_bytes = r_bytes + s_bytes + v_byte
return signature_bytes
# Constants
curve = SECP256k1.curve
n = SECP256k1.order
# Use the provided address and public key
address = "0x000000097C7e6f43bb3f225DB275B22C666402f1"
# Retrieved from the contract deployment transaction
public_key_hex = "0x4dd42356847875c8ae9fb131edaf9b823f63d6c00b850d678285e4f8eb403b7b4fc3da7548f9ffd09259f29cbf41b5e1daa0f83dcf02fa8dd3cd42647b6606cf"
public_key_bytes = bytes.fromhex(public_key_hex[2:])
public_key = VerifyingKey.from_string(public_key_bytes, curve=SECP256k1)
print("Target Account Address:", address)
print("Target Account Public Key:", public_key.to_string().hex())
while True:
# Choose arbitrary values for a and b
a = random.randint(1, n - 1)
b = random.randint(1, n - 1)
# Calculate r (Px)
aG = a * SECP256k1.generator
bH = b * public_key.pubkey.point #type:ignore
P = aG + bH
r = P.x()
# Calculate s and z
s = (r * pow(b, -1, n)) % n
z = (a * s) % n
# "Hash" the message (but actually use the calculated z value)
hash_z = number_to_string(z, SECP256k1.order)
signature = (28, number_to_string(r, SECP256k1.order), number_to_string(s, SECP256k1.order))
recovered_address = Account._recover_hash(hash_z, signature=vrs_to_signature_bytes(*signature).hex())
if recovered_address.lower() == address.lower():
print("Signature", vrs_to_signature_bytes(*signature).hex())
print("Generated hash", hash_z.hex())
print("Signature verification passed! The recovered address matches the provided address.")
break
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment