ecdsa-nonce-reuse-recover-private-key
Solution written and verified. Files produced in ~/ecdsa_recover/:
solution.md — the self-contained markdown deliverablesolve.js — executable solver + self-test (ran clean)Root cause: ECDSA reusing a nonce k lets you cancel out d between two signatures because s = k⁻¹(h + r·d) mod n. Subtracting gives k = (h1-h2)(s1-s2)⁻¹ mod n, and plugging k back in gives d = (s1·k-h1)r⁻¹ mod n.
Key trap: the moduli for every scalar operation is the curve group order n = 0x…0364141, not the field prime p. Every subtraction (h1-h2, s1-s2, s1·k-h1) must be normalized into [0, n) (JS BigInt with ((a % m) + m) % m) before inversion, or Fermat inversion returns a wrong residue class and the third-signature check fails.
Verification (node 22, solve.js): generated a random d/k, derived three signatures from the shared nonce, recovered d bit-for-bit:
expected d = 55824fd4e70d45a282e45f1d68b434763eaabd6ee21af931fe77ac02fbe44ba9
recovered = 55824fd4e70d45a282e45f1d68b434763eaabd6ee21af931fe77ac02fbe44ba9
d match : true
k match : true
third sig : true
The third signature reproduces exactly, so n, the modular inverses, and both recovery steps are correct. The verify check uses s3·k === h3 + r·d (mod n) to avoid a redundant second inverse.
All files are already self-consistent and runnable as-is for whatever randomized instance the platform hands you.
# Evidence - Problem class: ecdsa-nonce-reuse-recover-private-key - Model: openrouter/deepseek/deepseek-v4-flash-0731 - Solved: 2026-08-24T04:20:05.955Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Two ECDSA signatures over secp256k1 were created with the same nonce k for different messages; recover the signer private key d using only BigInt modular arithmetic (SHA-256 via Node crypto for hashing). Given r, s1, h1 and r, s2, h2 (h = SHA-256 digest of each message), compute k = (h1-h2)*(s1-s2)^-1 mod n and then d = (s1*k-h1)*r^-1 mod n, outputting d as a 64-char zero-padded lowercase hex string. The recovered key must reproduce a third provided signature, so any arithmetic slip or wrong curve-parameter constant fails verification.", "environment": "node20", "language": "js", "model": "openrouter/deepseek/deepseek-v4-flash-0731", "problem_class": "ecdsa-nonce-reuse-recover-private-key", "provider": "openrouter", "solved_at": "2026-08-24T04:20:05.955Z", "version": "20"}Solution written and verified. Files produced in ~/ecdsa_recover/:
solution.md — the self-contained markdown deliverablesolve.js — executable solver + self-test (ran clean)Root cause: ECDSA reusing a nonce k lets you cancel out d between two signatures because s = k⁻¹(h + r·d) mod n. Subtracting gives k = (h1-h2)(s1-s2)⁻¹ mod n, and plugging k back in gives d = (s1·k-h1)r⁻¹ mod n.
Key trap: the moduli for every scalar operation is the curve group order n = 0x…0364141, not the field prime p. Every subtraction (h1-h2, s1-s2, s1·k-h1) must be normalized into [0, n) (JS BigInt with ((a % m) + m) % m) before inversion, or Fermat inversion returns a wrong residue class and the third-signature check fails.
Verification (node 22, solve.js): generated a random d/k, derived three signatures from the shared nonce, recovered d bit-for-bit:
expected d = 55824fd4e70d45a282e45f1d68b434763eaabd6ee21af931fe77ac02fbe44ba9
recovered = 55824fd4e70d45a282e45f1d68b434763eaabd6ee21af931fe77ac02fbe44ba9
d match : true
k match : true
third sig : true
The third signature reproduces exactly, so n, the modular inverses, and both recovery steps are correct. The verify check uses s3·k === h3 + r·d (mod n) to avoid a redundant second inverse.
All files are already self-consistent and runnable as-is for whatever randomized instance the platform hands you.
# Evidence - Problem class: ecdsa-nonce-reuse-recover-private-key - Model: openrouter/deepseek/deepseek-v4-flash-0731 - Solved: 2026-08-24T04:20:05.955Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Two ECDSA signatures over secp256k1 were created with the same nonce k for different messages; recover the signer private key d using only BigInt modular arithmetic (SHA-256 via Node crypto for hashing). Given r, s1, h1 and r, s2, h2 (h = SHA-256 digest of each message), compute k = (h1-h2)*(s1-s2)^-1 mod n and then d = (s1*k-h1)*r^-1 mod n, outputting d as a 64-char zero-padded lowercase hex string. The recovered key must reproduce a third provided signature, so any arithmetic slip or wrong curve-parameter constant fails verification.", "environment": "node20", "language": "js", "model": "openrouter/deepseek/deepseek-v4-flash-0731", "problem_class": "ecdsa-nonce-reuse-recover-private-key", "provider": "openrouter", "solved_at": "2026-08-24T04:20:05.955Z", "version": "20"}