Skip to content

Commit

Permalink
feat: refactor Timing Safe Equal comparative using crypto library
Browse files Browse the repository at this point in the history
- Removed dependency tsscmp
  • Loading branch information
UlisesGascon committed Oct 7, 2024
1 parent 20d8b40 commit e49b536
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 9 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ app.listen(3000, () => {

Async callback verification, accepting `fn(err, user)`.

Note: It is recommended to use `crypto.timingSafeEqual(a, b)` [(Doc)](https://nodejs.org/api/crypto.html#cryptotimingsafeequala-b) to compare the user and password strings.

```js
connect()
.use(basicAuth(function(user, pass, fn){
Expand Down
28 changes: 22 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const timingSafeCompare = require('tsscmp');
const http = require('http');
const crypto = require('crypto');

/*!
* Connect - basicAuth
Expand All @@ -26,8 +26,10 @@ const http = require('http');
*
* connect()
* .use(connect.basicAuth(function(user, pass){
* return 'tj' == user && 'wahoo' == pass;
* return 'tj' === user && 'wahoo' === pass;
* }))
*
* Note: it is recommended to use `crypto.timingSafeEqual(a, b)` https://nodejs.org/api/crypto.html#cryptotimingsafeequala-b
*
* Async callback verification, accepting `fn(err, user)`.
*
Expand All @@ -50,11 +52,25 @@ module.exports = function basicAuth(callback, realm) {
password = realm;
if (typeof password !== 'string') throw new Error('password argument required');
realm = arguments[2];
callback = function(user, pass){
const usernameValid = timingSafeCompare(user, username);
const passwordValid = timingSafeCompare(pass, password);

callback = (user, pass) => {
const buffers = [
Buffer.from(user),
Buffer.from(pass),
Buffer.from(username),
Buffer.from(password)
];

// Determine the maximum length among all buffers
const maxLength = Math.max(...buffers.map(buf => buf.length));

// Pad each buffer to the maximum length
const paddedBuffers = buffers.map(buf => Buffer.concat([buf, Buffer.alloc(maxLength - buf.length)]));

const usernameValid = crypto.timingSafeEqual(paddedBuffers[0], paddedBuffers[2])
const passwordValid = crypto.timingSafeEqual(paddedBuffers[1], paddedBuffers[3])
return usernameValid && passwordValid;
}
};
}

realm = realm || 'Authorization Required';
Expand Down
3 changes: 0 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,5 @@
},
"scripts": {
"test": "make test"
},
"dependencies": {
"tsscmp": "^1.0.6"
}
}

0 comments on commit e49b536

Please sign in to comment.