Skip to content

Commit 652d991

Browse files
committed
restore xor algorithm for compareDigest
1 parent 962d66c commit 652d991

1 file changed

Lines changed: 7 additions & 15 deletions

File tree

src/cmap/auth/scram.ts

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ async function continueScramConversation(
186186
const r = await connection.command(ns(`${db}.$cmd`), saslContinueCmd, undefined);
187187
const parsedResponse = parsePayload(r.payload);
188188

189-
if (!(await compareDigest(ByteUtils.fromBase64(parsedResponse.v), serverSignature))) {
189+
if (!compareDigest(ByteUtils.fromBase64(parsedResponse.v), serverSignature)) {
190190
throw new MongoRuntimeError('Server returned an invalid signature');
191191
}
192192

@@ -342,25 +342,17 @@ async function HI(data: string, salt: Uint8Array, iterations: number, cryptoMeth
342342
return saltedData;
343343
}
344344

345-
async function compareDigest(lhs: Uint8Array, rhs: Uint8Array) {
345+
function compareDigest(lhs: Uint8Array, rhs: Uint8Array) {
346346
if (lhs.length !== rhs.length) {
347347
return false;
348348
}
349349

350-
// Compare values using a time-constant algorithm to prevent against timing attacks
351-
// The approach is called "Double HMAC Verification". The basic idea is:
352-
// 1. Generate a random key
353-
// 2. HMAC the random key with both values
354-
// 3. Compare the HMACs using an equality check
355-
356-
const randomKey = crypto.getRandomValues(new Uint8Array(32));
357-
const lhsHMAC = await HMAC('sha256', randomKey, lhs);
358-
const rhsHMAC = await HMAC('sha256', randomKey, rhs);
359-
const lhsHex = ByteUtils.toHex(lhsHMAC);
360-
const rhsHex = ByteUtils.toHex(rhsHMAC);
361-
const areEqual = lhsHex === rhsHex;
350+
let result = 0;
351+
for (let i = 0; i < lhs.length; i++) {
352+
result |= lhs[i] ^ rhs[i];
353+
}
362354

363-
return areEqual;
355+
return result === 0;
364356
}
365357

366358
export class ScramSHA1 extends ScramSHA {

0 commit comments

Comments
 (0)