Discovery

Given a message.txt
Message: 3343435f31735f4272306b336e
Signature (r,s): 81656283118670857341884602426840867029778987004268103130686475270399518147476,51070035169163094288170086161579499981349116068533637659570945874191030730099A public.pem
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKXNLO9XJZ3gSjZSBRCsIF6N14q7Z
kA6Z1VNKlaSBNgFRfk9z0/+AQfgRBqOUP1KSzPhAQOPR5+SXRIJeIjEKJg==
-----END PUBLIC KEY-----and a V_script.py
from Crypto.PublicKey import ECC
from Crypto.Hash import SHA256
from Crypto.Math._IntegerGMP import IntegerGMP
def generate_key():
return ECC.generate(curve='P-256')
def flawed_sign(private_key, message):
# Convert all values to IntegerGMP for consistent arithmetic
h = SHA256.new(message).digest()
h_int = IntegerGMP(int.from_bytes(h, 'big'))
n = private_key._curve.order
# Using predictable nonce (as IntegerGMP)
k = IntegerGMP(0xdeadbeef)
# ECDSA signing
curve = private_key._curve
K = int(k) * curve.G # Point multiplication requires int
r = IntegerGMP(int(K.x)) % n
# All operations with IntegerGMP
k_inv = k.inverse(n)
dr = private_key.d * r
h_plus_dr = h_int + dr
s = (k_inv * h_plus_dr) % n
return (int(r), int(s)) # Convert back to Python ints for output
if __name__ == "__main__":
key = generate_key()
# Save public key
with open("public.pem", "wt") as f:
f.write(key.public_key().export_key(format='PEM'))
message = b"XXXXXXXXXXXXXXXXXX"
signature = flawed_sign(key, message)
with open("message.txt", "wt") as f:
f.write(f"Message: {message.hex()}\n")
f.write(f"Signature (r,s): {signature[0]},{signature[1]}")
Lets get the flag
from Crypto.PublicKey import ECC
from Crypto.Hash import SHA256
from Crypto.Math.Numbers import Integer
import binascii
import re
# Constants
KNOWN_K = 0xdeadbeef
# Step 1: Load public key
with open("public.pem", "rt") as f:
pub_key = ECC.import_key(f.read())
curve = pub_key._curve
G = curve.G
n = int(curve.order)
# Step 2: Read message and signature
with open("message.txt", "r") as f:
content = f.read()
# Parse message and signature from text
msg_match = re.search(r"Message:\s*([0-9a-fA-F]+)", content)
sig_match = re.search(r"Signature \(r,s\):\s*(\d+),\s*(\d+)", content)
if not msg_match or not sig_match:
raise ValueError("Could not parse message or signature.")
msg_hex = msg_match.group(1)
r = int(sig_match.group(1))
s = int(sig_match.group(2))
message = bytes.fromhex(msg_hex)
# Step 3: Compute SHA256 hash of message
h = int.from_bytes(SHA256.new(message).digest(), byteorder='big')
# Step 4: Recover private key
r_inv = pow(r, -1, n)
d = ((s * KNOWN_K - h) * r_inv) % n
# Step 5: Reconstruct private key
priv_key = ECC.construct(curve='P-256', d=d)
# Step 6: Output results
print("✔️ Signature valid with public key.")
print(f"🔑 Recovered private key (d): {d}")
print(f"🏁 Recovered flag (message): {message.decode()}")
Running solver gave us the flag
PS C:\Users\saleh\Downloads\cryptooo> & C:/Users/saleh/AppData/Local/Programs/Python/Python313/python.exe c:/Users/saleh/Downloads/cryptooo/discovery.py
✔️ Signature valid with public key.
🔑 Recovered private key (d): 54557082544614123842088576588847111891417741407876865337994383802864000837462
🏁 Recovered flag (message): 3CC_1s_Br0k3nLast updated
Was this helpful?