-
Notifications
You must be signed in to change notification settings - Fork 32
Description
1: JavaScript: All Shares Use the Same x-Coordinate
1.1 Bug Description
In jsbtc/shamir.js, the loop to generate shares reuses the same 1) for all shares, because ePointer++ is missing. This means each share is the same point, repeated.
// jsbtc/shamir.js ≈L113–120
let ePointer = 0;
for (let i = 0; i < n; i++) {
let x = getShareX(e[ePointer]);
let y = getShareY(secret, x); // e.g. y = f(x)
shares.push(encode(x, y));
// ePointer++; ← MISSING: so x = e[0] always
}1.2 Impact
The system degenerates into 1-of-n sharing: all shares are just copies of the same point. An attacker with any single share can trivially recover the secret by interpreting the constant term.
1.3 Proof-of-Concept (PoC)
Split a secret into 5 shares, then decode all their
// All x-values will be the same (e.g. 1)
shares.map(s => decodeX(s));1.4 Attack Methodology
Obtain a single share (e.g. via phishing). Since all shares are duplicates, you get the full secret with just one.
1.5 Recommendations
Fix the share loop to increment the entropy pointer (ePointer++) after each iteration so
2: JavaScript: Infinite Loop When Entropy Runs Out
2.1 Bug Description
When the entropy buffer is exhausted inside the generateShares function, the code attempts to regenerate it—but the logic to replace the exhausted buffer is broken, causing an infinite loop.
// jsbtc/shamir.js ≈L80–95
while (q.length < threshold - 1) {
if (ePointer < e.length) {
q.push(e[ePointer]);
ePointer++;
} else {
// Missing logic to refill e or reset ePointer!
// Just keeps looping forever
}
}2.2 Impact
Denial-of-Service (DoS): If a long-running session depletes entropy, share generation hangs indefinitely, freezing any UI or CLI dependent on it.
2.3 Proof-of-Concept (PoC)
Set a small e array and high threshold, e.g., e = [1,2] and threshold = 5. The loop never exits.
2.4 Attack Methodology
Trigger high-threshold splits in constrained environments (e.g., browser wallets). It halts and becomes unusable.
2.5 Recommendations
Add buffer refill logic:
e = crypto.getRandomValues(new Uint8Array(entropySize));
ePointer = 0;Or switch to per-coefficient secure randomness using crypto.getRandomValues directly.
3: JavaScript: Coefficient Collisions Break Polynomial
3.1 Bug Description
The polynomial coefficients are pulled directly from a byte buffer. There’s no check for collisions, so it’s common for multiple coefficients to be the same—making the interpolation degenerate or invalid.
// jsbtc/shamir.js
q.push(e[ePointer]); // no check if value already in q[]3.2 Impact
If any coefficient repeats (especially the leading ones), the polynomial may become degenerate or unsolvable. Shares can interpolate to an incorrect or undefined secret.
3.3 Proof-of-Concept (PoC)
Force buffer with repeated values, e.g. e = [1,1,1,1,...], and check if share reconstruction fails or returns wrong secret.
3.4 Attack Methodology
Deliberately inject repeated coefficients or lower-entropy buffers (e.g., tampered hardware RNG). Victims unknowingly back up invalid shares.
3.5 Recommendations
Introduce logic to enforce coefficient uniqueness—or switch to generating random numbers per coefficient using crypto.getRandomValues to ensure sufficient entropy and randomness.
4: JavaScript: Insecure Randomness from Math.random
4.1 Bug Description
Entropy and randomness are derived from Math.random() in some places, which is not cryptographically secure.
// jsbtc/shamir.js or indirectly from random.js
let r = Math.random(); // used to build entropy4.2 Impact
Math.random() is predictable and vulnerable to timing/state recovery attacks. An attacker with some outputs can reproduce the RNG state and guess all coefficients.
4.3 Proof-of-Concept (PoC)
Generate multiple share sets and observe entropy patterns or repeatability across sessions.
4.4 Attack Methodology
Observe or leak partial entropy data. Reverse the seed or state of the Math.random generator to derive secret shares and the original secret.
4.5 Recommendations
Replace all uses of Math.random() with:
window.crypto.getRandomValues(new Uint8Array(...));Add CI checks to prevent Math.random() in any crypto path.