LionC / express-basic-auth

Plug & play basic auth middleware for express
325 stars 57 forks source link

[Question] safeCompare function #62

Closed manooi closed 6 months ago

manooi commented 6 months ago

Hi,

I use this library to secure my NestJS Swagger endpoints, and it works great! I wanted to see how it works by digging around in the source code, and I found something that seemed odd to me.

function safeCompare(userInput, secret) {
    const userInputLength = Buffer.byteLength(userInput)
    const secretLength = Buffer.byteLength(secret)

    const userInputBuffer = Buffer.alloc(userInputLength, 0, 'utf8')
    userInputBuffer.write(userInput)
    const secretBuffer = Buffer.alloc(userInputLength, 0, 'utf8') // Question 1
    secretBuffer.write(secret)

    return !!(timingSafeEqual(userInputBuffer, secretBuffer) & userInputLength === secretLength) // Question 2
}

Here're my questions: -

  1. Why does it use userInputLength intead of secretLength when allocating secretBuffer?
  2. Why does it use bitwise & instead of the logical &&?

Thanks

LionC commented 6 months ago
  1. Why does it use userInputLength intead of secretLength when allocating secretBuffer?

Because this way, the runtime behaviour of the function will only depend on the input and not on the secret, securing a possible attack vector to sniff for the length of the secret via statistical analysis etc

  1. Why does it use bitwise & instead of the logical &&?

Because && shortcuts if the first condition is false, making the timing depend on the conditions being true or false. & does not shortcut and will always evaluate both sides. This helps against timing attacks again (and is also why the README says to use & on the consumer side as well).

manooi commented 6 months ago

Thanks 🙏