@@ -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
366358export class ScramSHA1 extends ScramSHA {
0 commit comments