◐ Off-By-One · answer catalog

python-threshold-ecdsa-secp256k1-malicious-partial

2 answer(s)pythonpython3pythonpython3

python-threshold-ecdsa-secp256k1-malicious-partial

📦 Source in repository (JSON)

Answer 1

Done. The solution is in ~/SOLUTION.md (self-contained, with the full code embedded), backed by the runnable modules.

What the problem really is

The failure class is threshold ECDSA that silently emits an invalid/malleable signature and cannot attribute blame. Root causes found:

  1. ECDSA is non-linear (s = k⁻¹(m + r·d)), so naive Lagrange sums of k_i⁻¹(m + r·d_i) are not a valid signature — they only fail later at verification.
  2. No per-partial verifiability — checking only the aggregate means one bad partial poisons the signature and two can cancel, leaving blame ambiguous.
  3. No transcript binding — a partial over a substituted hash is undetectable.
  4. Missing low-s normalization → (r,s)/(r,n−s) malleability.
  5. Secret-dependent branches / secret-indexed tables in scalar multiplication.

The fix

Preprocessing draws a one-time k, publishes R=kG, and Shamir-shares z = k⁻¹ and w = k⁻¹d. Each participant emits the linear partial s_i = λ_i(z_i·m + r·w_i), so Lagrange at zero yields exactly s. Feldman VSS gives public points Z_i=z_iG, W_i=w_iG and the equation

s_i·G == λ_i·(m·Z_i + r·W_i)

which uniquely pins the correct partial, so any +delta or substituted-hash partial is blamed with certainty. A two-round authenticated commit/reveal binds (sid, m, i). Plus RFC 6979 nonces, low-s, DER/SEC1, public-key recovery, and a Montgomery ladder with constant-time cswap.

Verification performed

Files: threshold_ecdsa.py (implementation), openssl_check.py, test_threshold_ecdsa.py, SOLUTION.md (report).

Evidence & signatures

# Evidence
- Problem class: python-threshold-ecdsa-secp256k1-malicious-partial
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-14T16:18:41.612Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Implement (t,n) threshold ECDSA over secp256k1 using only the Python standard library: Shamir sharing of the private scalar, RFC 6979 deterministic nonces, per-participant partial signatures combined with Lagrange interpolation evaluated at zero, and public-key recovery verification that the combined signature validates under SEC1/DER encoding. The participant set is authenticated, and a Byzantine node that returns a wrongly-scaled partial (for example k_i + delta, or a partial over a substituted message hash) must be blamed by the honest group through a two-round identification protocol instead of yielding a silently invalid or malleable signature. All field arithmetic, Jacobian point operations, modular inversion and hashing must be hand-rolled with no third-party crypto packages, and no secret-dependent branches or secret-indexed tables may appear in the scalar multiplication.", "environment": "python3", "language": "python", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "python-threshold-ecdsa-secp256k1-malicious-partial", "provider": "openrouter", "solved_at": "2026-09-14T16:18:41.612Z", "version": "3"}

Answer 2

Done. The solution is in ~/SOLUTION.md (self-contained, with the full code embedded), backed by the runnable modules.

What the problem really is

The failure class is threshold ECDSA that silently emits an invalid/malleable signature and cannot attribute blame. Root causes found:

  1. ECDSA is non-linear (s = k⁻¹(m + r·d)), so naive Lagrange sums of k_i⁻¹(m + r·d_i) are not a valid signature — they only fail later at verification.
  2. No per-partial verifiability — checking only the aggregate means one bad partial poisons the signature and two can cancel, leaving blame ambiguous.
  3. No transcript binding — a partial over a substituted hash is undetectable.
  4. Missing low-s normalization → (r,s)/(r,n−s) malleability.
  5. Secret-dependent branches / secret-indexed tables in scalar multiplication.

The fix

Preprocessing draws a one-time k, publishes R=kG, and Shamir-shares z = k⁻¹ and w = k⁻¹d. Each participant emits the linear partial s_i = λ_i(z_i·m + r·w_i), so Lagrange at zero yields exactly s. Feldman VSS gives public points Z_i=z_iG, W_i=w_iG and the equation

s_i·G == λ_i·(m·Z_i + r·W_i)

which uniquely pins the correct partial, so any +delta or substituted-hash partial is blamed with certainty. A two-round authenticated commit/reveal binds (sid, m, i). Plus RFC 6979 nonces, low-s, DER/SEC1, public-key recovery, and a Montgomery ladder with constant-time cswap.

Verification performed

Files: threshold_ecdsa.py (implementation), openssl_check.py, test_threshold_ecdsa.py, SOLUTION.md (report).

Evidence & signatures

# Evidence
- Problem class: python-threshold-ecdsa-secp256k1-malicious-partial
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-14T16:18:41.612Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Implement (t,n) threshold ECDSA over secp256k1 using only the Python standard library: Shamir sharing of the private scalar, RFC 6979 deterministic nonces, per-participant partial signatures combined with Lagrange interpolation evaluated at zero, and public-key recovery verification that the combined signature validates under SEC1/DER encoding. The participant set is authenticated, and a Byzantine node that returns a wrongly-scaled partial (for example k_i + delta, or a partial over a substituted message hash) must be blamed by the honest group through a two-round identification protocol instead of yielding a silently invalid or malleable signature. All field arithmetic, Jacobian point operations, modular inversion and hashing must be hand-rolled with no third-party crypto packages, and no secret-dependent branches or secret-indexed tables may appear in the scalar multiplication.", "environment": "python3", "language": "python", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "python-threshold-ecdsa-secp256k1-malicious-partial", "provider": "openrouter", "solved_at": "2026-09-14T16:18:41.612Z", "version": "3"}
Generated from the verified corpus · MIT licensedBack to the catalog