Ghost/core/server/lib/security/tokens.js
Katharina Irrgang 4bd211b42a Added Node v10 Support (#10058)
* Added Node v10 Support

no issue

Signed-off-by: kirrg001 <katharina.irrgang@googlemail.com>

* Bump amperize to version 0.3.8

no issue

* Bump mysql to version 2.16.0

no issue

- mysql 2.15.0 uses a deprecated notation for timers
- e.g. timers.unenroll()

* Bump sub dependencies

no issue

- e.g. knex-migrator used mysql 2.15.0

* Bump dependencies

no issue

* Replaced `new Buffer` with `Buffer.from`

no issue

- Buffer() is deprecated due to security and usability issues.
- https://nodejs.org/en/docs/guides/buffer-constructor-deprecation/
2018-10-30 15:45:51 +07:00

116 lines
3.0 KiB
JavaScript

const crypto = require('crypto');
module.exports.generateFromContent = function generateFromContent(options) {
options = options || {};
const hash = crypto.createHash('sha256'),
content = options.content;
let text = '';
hash.update(content);
text += [content, hash.digest('base64')].join('|');
return Buffer.from(text).toString('base64');
};
module.exports.generateFromEmail = function generateFromEmail(options) {
options = options || {};
const hash = crypto.createHash('sha256'),
expires = options.expires,
email = options.email,
secret = options.secret;
let text = '';
hash.update(String(expires));
hash.update(email.toLocaleLowerCase());
hash.update(String(secret));
text += [expires, email, hash.digest('base64')].join('|');
return Buffer.from(text).toString('base64');
};
module.exports.resetToken = {
generateHash: function generateHash(options) {
options = options || {};
var hash = crypto.createHash('sha256'),
expires = options.expires,
email = options.email,
dbHash = options.dbHash,
password = options.password,
text = '';
hash.update(String(expires));
hash.update(email.toLocaleLowerCase());
hash.update(password);
hash.update(String(dbHash));
text += [expires, email, hash.digest('base64')].join('|');
return Buffer.from(text).toString('base64');
},
extract: function extract(options) {
options = options || {};
var token = options.token,
tokenText = Buffer.from(token, 'base64').toString('ascii'),
parts,
expires,
email;
parts = tokenText.split('|');
// Check if invalid structure
if (!parts || parts.length !== 3) {
return false;
}
expires = parseInt(parts[0], 10);
email = parts[1];
return {
expires: expires,
email: email
};
},
compare: function compare(options) {
options = options || {};
var tokenToCompare = options.token,
parts = exports.resetToken.extract({token: tokenToCompare}),
dbHash = options.dbHash,
password = options.password,
generatedToken,
diff = 0,
i;
if (isNaN(parts.expires)) {
return false;
}
// Check if token is expired to prevent replay attacks
if (parts.expires < Date.now()) {
return false;
}
generatedToken = exports.resetToken.generateHash({
email: parts.email,
expires: parts.expires,
dbHash: dbHash,
password: password
});
if (tokenToCompare.length !== generatedToken.length) {
diff = 1;
}
for (i = tokenToCompare.length - 1; i >= 0; i = i - 1) {
diff |= tokenToCompare.charCodeAt(i) ^ generatedToken.charCodeAt(i);
}
return diff === 0;
}
};