Title: Critical Shamir Secret Sharing flaws: unrecoverable share generation and silent incorrect recovery (Python implementation)
Summary
Multiple critical issues were identified in the Python implementation of Shamir Secret Sharing ("pybtc/functions/shamir.py") that break core guarantees of the scheme:
- Invalid share sets can be generated (unrecoverable secrets)
- Recovery with insufficient shares silently returns incorrect data
- Corrupted shares are not detected during reconstruction
These flaws may result in irreversible loss of funds in real-world wallet backup scenarios.
Environment
- Python version: 3.x
- Library: pybtc (latest master at time of testing)
Issue 1 — Missing validation ("threshold > total")
Description
The implementation does not enforce:
threshold <= total
Proof of Concept
from pybtc.functions.shamir import split_secret
shares = split_secret(3, 2, b"hello")
print(shares)
Actual Behavior
- Shares are successfully generated
- However, reconstruction is impossible because threshold exceeds total shares
Expected Behavior
- Function should raise an exception
Impact
- Users may unknowingly create irrecoverable backups
- Leads to permanent loss of access to funds
Issue 2 — Silent incorrect recovery with insufficient shares
Proof of Concept
from pybtc.functions.shamir import split_secret, restore_secret
secret = b"hello123"
shares = split_secret(3, 5, secret)
selected = dict(list(shares.items())[:2])
restored = restore_secret(selected)
print(restored)
Actual Output
b'\xb8\xcc\xe6\xb0\xc3\xccq\x14'
Expected Behavior
- Function should raise an error due to insufficient shares
Actual Behavior
- Function returns structurally valid but incorrect output without any error
Impact
- Users may be misled into believing recovery succeeded
- Results in silent corruption of the recovered secret
Issue 3 — Corrupted share not detected
Proof of Concept
from pybtc.functions.shamir import split_secret, restore_secret
secret = b"hello123"
shares = split_secret(3, 5, secret)
selected = dict(list(shares.items())[:3])
key = list(selected.keys())[0]
bad = dict(selected)
bad[key] = bytes([bad[key][0] ^ 1]) + bad[key][1:]
restored = restore_secret(bad)
print(restored)
Actual Output
b"qello123"
Expected Behavior
- Function should detect corruption and raise an error
Actual Behavior
- Function silently returns incorrect secret
Impact
- Data integrity is not verified
- Leads to undetected recovery errors
Cross-Implementation Observation
The JavaScript implementation includes stricter validation (e.g., "threshold > total" check), while the Python version does not.
This inconsistency indicates lack of unified validation across implementations and increases the risk of misuse.
Security Impact
These issues combined create serious risks:
- Irreversible loss of funds
- Creation of unrecoverable backups
- Silent incorrect recovery
- Undetected data corruption
This behavior violates the core guarantee of Shamir Secret Sharing:
«Reconstruction should either succeed correctly or fail explicitly.»
Suggested Fixes
- Add validation in "split_secret":
if threshold > total:
raise ValueError("threshold cannot exceed total shares")
-
Enforce minimum share count during recovery
-
Add integrity verification (e.g., checksum validation)
-
Fail explicitly on corrupted or insufficient data
Conclusion
The current implementation violates fundamental expectations of Shamir Secret Sharing in terms of:
- Correctness
- Safety
- Reliability
These issues should be treated as critical.
Title: Critical Shamir Secret Sharing flaws: unrecoverable share generation and silent incorrect recovery (Python implementation)
Summary
Multiple critical issues were identified in the Python implementation of Shamir Secret Sharing ("pybtc/functions/shamir.py") that break core guarantees of the scheme:
These flaws may result in irreversible loss of funds in real-world wallet backup scenarios.
Environment
Issue 1 — Missing validation ("threshold > total")
Description
The implementation does not enforce:
threshold <= total
Proof of Concept
from pybtc.functions.shamir import split_secret
shares = split_secret(3, 2, b"hello")
print(shares)
Actual Behavior
Expected Behavior
Impact
Issue 2 — Silent incorrect recovery with insufficient shares
Proof of Concept
from pybtc.functions.shamir import split_secret, restore_secret
secret = b"hello123"
shares = split_secret(3, 5, secret)
selected = dict(list(shares.items())[:2])
restored = restore_secret(selected)
print(restored)
Actual Output
b'\xb8\xcc\xe6\xb0\xc3\xccq\x14'
Expected Behavior
Actual Behavior
Impact
Issue 3 — Corrupted share not detected
Proof of Concept
from pybtc.functions.shamir import split_secret, restore_secret
secret = b"hello123"
shares = split_secret(3, 5, secret)
selected = dict(list(shares.items())[:3])
key = list(selected.keys())[0]
bad = dict(selected)
bad[key] = bytes([bad[key][0] ^ 1]) + bad[key][1:]
restored = restore_secret(bad)
print(restored)
Actual Output
b"qello123"
Expected Behavior
Actual Behavior
Impact
Cross-Implementation Observation
The JavaScript implementation includes stricter validation (e.g., "threshold > total" check), while the Python version does not.
This inconsistency indicates lack of unified validation across implementations and increases the risk of misuse.
Security Impact
These issues combined create serious risks:
This behavior violates the core guarantee of Shamir Secret Sharing:
«Reconstruction should either succeed correctly or fail explicitly.»
Suggested Fixes
if threshold > total:
raise ValueError("threshold cannot exceed total shares")
Enforce minimum share count during recovery
Add integrity verification (e.g., checksum validation)
Fail explicitly on corrupted or insufficient data
Conclusion
The current implementation violates fundamental expectations of Shamir Secret Sharing in terms of:
These issues should be treated as critical.