UNPKG

node-identity-server

Version:

A package that allows you to verify & create identity server 2/3/4 hashes in nodeJS

210 lines (160 loc) 8.59 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _crypto = require('crypto'); var _crypto2 = _interopRequireDefault(_crypto); var _util = require('util'); var _util2 = _interopRequireDefault(_util); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var pbkdf2Async = _util2.default.promisify(_crypto2.default.pbkdf2); var HashPasswordv3 = function () { function HashPasswordv3() { _classCallCheck(this, HashPasswordv3); } _createClass(HashPasswordv3, [{ key: 'verifyPassword', value: function () { var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(password, hashedPassword) { var decodedBuffer, iteration, key, saltLength, salt, subkeyLength, expectedSubkey, acutalSubkey; return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: decodedBuffer = null; if (hashedPassword) { decodedBuffer = Buffer.from(hashedPassword, 'base64'); } iteration = 10000; key = decodedBuffer[0]; saltLength = this.readNetworkByteOrder(decodedBuffer, 9); if (!(saltLength < 128 / 8)) { _context.next = 7; break; } return _context.abrupt('return', false); case 7: _context.next = 9; return _crypto2.default.randomBytes(16); case 9: salt = _context.sent; // take the salt from the stored hash in the database. // we effectively overwrite the bytes here from our random buffer. decodedBuffer.copy(salt, 0, 13, 13 + saltLength); subkeyLength = decodedBuffer.length - 13 - saltLength; if (!(subkeyLength < 128 / 8)) { _context.next = 14; break; } return _context.abrupt('return', false); case 14: expectedSubkey = new Buffer(32); decodedBuffer.copy(expectedSubkey, 0, 13 + saltLength, 13 + saltLength + expectedSubkey.length); _context.next = 18; return pbkdf2Async(password, salt, 10000, 32, 'sha256'); case 18: acutalSubkey = _context.sent; return _context.abrupt('return', this.areBuffersEqual(acutalSubkey, expectedSubkey)); case 20: case 'end': return _context.stop(); } } }, _callee, this); })); function verifyPassword(_x, _x2) { return _ref.apply(this, arguments); } return verifyPassword; }() }, { key: 'hashPassword', value: function () { var _ref2 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(password) { var salt, subkey, outputBytes; return regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: _context2.prev = 0; _context2.next = 3; return _crypto2.default.randomBytes(16); case 3: salt = _context2.sent; _context2.next = 6; return pbkdf2Async(password, salt, 10000, 32, 'sha256'); case 6: subkey = _context2.sent; outputBytes = new Buffer(13 + salt.length + subkey.length); // Write in the format marker outputBytes[0] = 0x01; // Write out the byte order this.writeNetworkByteOrder(outputBytes, 1, 1); this.writeNetworkByteOrder(outputBytes, 5, 10000); this.writeNetworkByteOrder(outputBytes, 9, salt.length); salt.copy(outputBytes, 13, 0, 16); subkey.copy(outputBytes, 13 + salt.length, 0, subkey.length); return _context2.abrupt('return', outputBytes.toString('base64')); case 17: _context2.prev = 17; _context2.t0 = _context2['catch'](0); new Error(_context2.t0); case 20: case 'end': return _context2.stop(); } } }, _callee2, this, [[0, 17]]); })); function hashPassword(_x3) { return _ref2.apply(this, arguments); } return hashPassword; }() /** * Writes the appropriate bytes into available slots * @param buffer * @param offset * @param value */ }, { key: 'writeNetworkByteOrder', value: function writeNetworkByteOrder(buffer, offset, value) { buffer[offset + 0] = value >> 0; buffer[offset + 1] = value >> 8; buffer[offset + 2] = value >> 16; buffer[offset + 3] = value >> 24; } /** * Reads the bytes back out using an offset. * @param buffer * @param offset * @returns {number} */ }, { key: 'readNetworkByteOrder', value: function readNetworkByteOrder(buffer, offset) { return buffer[offset + 0] << 24 | buffer[offset + 1] << 16 | buffer[offset + 2] << 8 | buffer[offset + 3]; } }, { key: 'areBuffersEqual', value: function areBuffersEqual(bufA, bufB) { var len = bufA.length; if (len !== bufB.length) { return false; } for (var i = 0; i < len; i++) { if (bufA.readUInt8(i) !== bufB.readUInt8(i)) { return false; } } return true; } }]); return HashPasswordv3; }(); exports.default = HashPasswordv3; //# sourceMappingURL=HashPasswordv3.js.map