- Branching timing leaks
- powm leaks the value of
e
|
function powm(x, e, m) { |
|
assert(m > 0n); |
|
|
|
if (e < 0n) { |
|
x = invert(x, m); |
|
e = -e; |
|
} else { |
|
x = mod(x, m); |
|
} |
|
|
|
if (e <= U32_MAX) |
|
return rtl(x, e, m); |
|
|
|
return slide(x, e, m); |
|
} |
|
|
|
function rtl(x, e, m) { |
|
let r = 1n; |
|
|
|
while (e > 0n) { |
|
if ((e & 1n) === 1n) |
|
r = (r * x) % m; |
|
|
|
x = (x * x) % m; |
|
e >>= 1n; |
|
} |
|
|
|
return r; |
|
} |
|
if ((e & 1n) === 1n) |
|
r = (r * x) % m; |
|
|
|
x = (x * x) % m; |
|
e >>= 1n; |
- (This also breaks any modular inversion that relies on
fermat())
I wrote a library that implements constant-time algorithms in TypeScript if you want to mitigate these risks.
Further reading: [1] [2]
bcrypto/lib/native/bn.js
Line 3556 in b73dbc6
bcrypto/lib/native/bn.js
Line 3435 in b73dbc6
ebcrypto/lib/native/bn.js
Lines 3869 to 3897 in b73dbc6
bcrypto/lib/native/bn.js
Lines 3889 to 3893 in b73dbc6
fermat())I wrote a library that implements constant-time algorithms in TypeScript if you want to mitigate these risks.
Further reading: [1] [2]