mirror of
https://github.com/openpgpjs/openpgpjs.git
synced 2026-03-15 04:45:10 +00:00
Use constant-time select in modExp (#1984)
modExp is used in some RSA, DSA and ElGamal operations. With native bigints, the constant-time select no longer introduces a considerable slowdown, so we switch to that to avoid secret-dependent branching, which in principle enables e.g. cache timing attacks (NB: these are still not relevant for our threat model). Thanks to Yayu Wang, Kjell Dankert and Aastha Mehta from the University of British Columbia for reporting the potential security issue and validating the fix.
This commit is contained in:
@@ -22,6 +22,18 @@ export function mod(a: bigint, m: bigint) {
|
||||
return reduced < _0n ? reduced + m : reduced;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return either `a` or `b` based on `cond`, in algorithmic constant time.
|
||||
* @param {BigInt} cond
|
||||
* @param {BigInt} a
|
||||
* @param {BigInt} b
|
||||
* @returns `a` if `cond` is `1n`, `b` otherwise
|
||||
*/
|
||||
function selectBigInt(cond: 0n | 1n, a: bigint, b: bigint) {
|
||||
const mask = -cond; // ~0n === -1n
|
||||
return (a & mask) | (b & ~mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute modular exponentiation using square and multiply
|
||||
* @param {BigInt} a - Base
|
||||
@@ -40,12 +52,12 @@ export function modExp(b: bigint, e: bigint, n: bigint) {
|
||||
x %= n;
|
||||
let r = BigInt(1);
|
||||
while (exp > _0n) {
|
||||
const lsb = exp & _1n;
|
||||
const lsb = (exp & _1n) as 1n | 0n;
|
||||
exp >>= _1n; // e / 2
|
||||
// Always compute multiplication step, to reduce timing leakage
|
||||
const rx = (r * x) % n;
|
||||
// Update r only if lsb is 1 (odd exponent)
|
||||
r = lsb ? rx : r;
|
||||
r = selectBigInt(lsb, rx, r);
|
||||
x = (x * x) % n; // Square
|
||||
}
|
||||
return r;
|
||||
|
||||
Reference in New Issue
Block a user