Created
June 12, 2025 04:26
-
-
Save secdev02/3a1b6b57760b75f2c89dd6bf6b27a6b9 to your computer and use it in GitHub Desktop.
SHALL WE PLAY A GAME?
This file contains hidden or 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
#!/usr/bin/env python3 | |
""" | |
Script to compute a public key on secp256k1 using a custom generator point. | |
""" | |
import hashlib | |
import base58 | |
# secp256k1 curve parameters | |
P = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F # Field prime | |
A = 0 # Curve parameter a | |
B = 7 # Curve parameter b | |
N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 # Order of the curve | |
# Standard secp256k1 generator point G | |
STANDARD_GX = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 | |
STANDARD_GY = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 | |
# Custom generator point (instead of standard G) | |
CUSTOM_GX = 0x3b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63 | |
CUSTOM_GY = 0x3f3979bf72ae8202983dc989aec7f2ff2ed91bdd69ce02fc0700ca100e59ddf3 | |
# Private key | |
PRIVATE_KEY = 0x00000000000000000000000000000000000000000000ea1a5c66dcc11b5ad180 | |
def mod_inverse(a, m): | |
"""Compute modular inverse using extended Euclidean algorithm.""" | |
if a < 0: | |
a = (a % m + m) % m | |
g, x, _ = extended_gcd(a, m) | |
if g != 1: | |
raise Exception('Modular inverse does not exist') | |
return x % m | |
def extended_gcd(a, b): | |
"""Extended Euclidean Algorithm.""" | |
if a == 0: | |
return b, 0, 1 | |
gcd, x1, y1 = extended_gcd(b % a, a) | |
x = y1 - (b // a) * x1 | |
y = x1 | |
return gcd, x, y | |
def point_add(x1, y1, x2, y2): | |
"""Add two points on the elliptic curve.""" | |
if x1 is None: # Point at infinity | |
return x2, y2 | |
if x2 is None: # Point at infinity | |
return x1, y1 | |
if x1 == x2: | |
if y1 == y2: | |
# Point doubling | |
s = (3 * x1 * x1 + A) * mod_inverse(2 * y1, P) % P | |
else: | |
# Points are inverses, result is point at infinity | |
return None, None | |
else: | |
# Point addition | |
s = (y2 - y1) * mod_inverse(x2 - x1, P) % P | |
x3 = (s * s - x1 - x2) % P | |
y3 = (s * (x1 - x3) - y1) % P | |
return x3, y3 | |
def point_multiply(k, x, y): | |
"""Multiply a point by a scalar using double-and-add method.""" | |
if k == 0: | |
return None, None # Point at infinity | |
if k == 1: | |
return x, y | |
result_x, result_y = None, None # Point at infinity | |
addend_x, addend_y = x, y | |
while k: | |
if k & 1: | |
result_x, result_y = point_add(result_x, result_y, addend_x, addend_y) | |
addend_x, addend_y = point_add(addend_x, addend_y, addend_x, addend_y) | |
k >>= 1 | |
return result_x, result_y | |
def sha256(data): | |
"""Compute SHA-256 hash.""" | |
return hashlib.sha256(data).digest() | |
def ripemd160(data): | |
"""Compute RIPEMD-160 hash.""" | |
return hashlib.new('ripemd160', data).digest() | |
def hash160(data): | |
"""Compute HASH160 (SHA-256 followed by RIPEMD-160).""" | |
return ripemd160(sha256(data)) | |
def encode_base58_check(payload, version=0x00): | |
"""Encode data with Base58Check encoding.""" | |
# Add version byte | |
versioned_payload = bytes([version]) + payload | |
# Calculate checksum (first 4 bytes of double SHA-256) | |
checksum = sha256(sha256(versioned_payload))[:4] | |
# Concatenate and encode | |
full_payload = versioned_payload + checksum | |
return base58.b58encode(full_payload).decode('ascii') | |
def compute_and_display_pubkey(gx, gy, generator_name): | |
"""Compute and display public key for a given generator point.""" | |
print(f"\n{generator_name} GENERATOR:") | |
print("=" * (len(generator_name) + 11)) | |
print(f"Generator Point:") | |
print(f" X: 0x{gx:x}") | |
print(f" Y: 0x{gy:x}") | |
# Verify the generator point is on the curve | |
if (gy * gy - gx * gx * gx - B) % P != 0: | |
print(f"ERROR: {generator_name} generator point is not on the secp256k1 curve!") | |
return | |
print("Generator point verified to be on the curve.") | |
# Compute public key: Q = private_key * G | |
pub_x, pub_y = point_multiply(PRIVATE_KEY, gx, gy) | |
if pub_x is None or pub_y is None: | |
print("ERROR: Public key computation resulted in point at infinity!") | |
return | |
print(f"\nPUBLIC KEY RESULTS ({generator_name}):") | |
print("=" * (len(generator_name) + 22)) | |
# 1. Hexadecimal format (uncompressed) | |
uncompressed_hex = f"04{pub_x:064x}{pub_y:064x}" | |
print(f"Hex (Uncompressed): {uncompressed_hex}") | |
# 2. Hexadecimal format (compressed) | |
prefix = "02" if pub_y % 2 == 0 else "03" | |
compressed_hex = f"{prefix}{pub_x:064x}" | |
print(f"Hex (Compressed): {compressed_hex}") | |
# 3. Decimal format | |
print(f"Decimal X: {pub_x}") | |
print(f"Decimal Y: {pub_y}") | |
# 4. Bitcoin address format (compressed public key) | |
compressed_pubkey_bytes = bytes.fromhex(compressed_hex) | |
pubkey_hash = hash160(compressed_pubkey_bytes) | |
bitcoin_address = encode_base58_check(pubkey_hash, version=0x00) | |
print(f"Bitcoin Address (P2PKH): {bitcoin_address}") | |
print(f"\nVERIFICATION ({generator_name}):") | |
print("=" * (len(generator_name) + 16)) | |
print(f"Public key point is on curve: {(pub_y * pub_y - pub_x * pub_x * pub_x - B) % P == 0}") | |
def main(): | |
print("secp256k1 Public Key Computation") | |
print("=" * 40) | |
print(f"Private Key: 0x{PRIVATE_KEY:x}") | |
# Compute public key using standard secp256k1 generator G | |
compute_and_display_pubkey(STANDARD_GX, STANDARD_GY, "STANDARD") | |
# Compute public key using custom generator point | |
compute_and_display_pubkey(CUSTOM_GX, CUSTOM_GY, "CUSTOM") | |
if __name__ == "__main__": | |
main() |
This file contains hidden or 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
Create public keys on curve with different Generator | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment