diff --git a/lib/client.js b/lib/client.js index 72edd699..2016a6ff 100644 --- a/lib/client.js +++ b/lib/client.js @@ -106,10 +106,7 @@ Client.prototype.connect = function (callback) { // password request handling con.on('authenticationMD5Password', checkPgPass(function (msg) { - var inner = utils.md5(self.password + self.user) - var outer = utils.md5(Buffer.concat([Buffer.from(inner), msg.salt])) - var md5password = 'md5' + outer - con.password(md5password) + con.password(utils.postgresMd5PasswordHash(self.user, self.password, msg.salt)) })) con.once('backendKeyData', function (msg) { diff --git a/lib/utils.js b/lib/utils.js index 352a02fb..575fb056 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -138,6 +138,13 @@ const md5 = function (string) { return crypto.createHash('md5').update(string, 'utf-8').digest('hex') } +// See AuthenticationMD5Password at https://www.postgresql.org/docs/current/static/protocol-flow.html +const postgresMd5PasswordHash = function (user, password, salt) { + var inner = md5(password + user) + var outer = md5(Buffer.concat([Buffer.from(inner), salt])) + return 'md5' + outer +} + module.exports = { prepareValue: function prepareValueWrapper (value) { // this ensures that extra arguments do not get passed into prepareValue @@ -145,5 +152,6 @@ module.exports = { return prepareValue(value) }, normalizeQueryConfig: normalizeQueryConfig, + postgresMd5PasswordHash: postgresMd5PasswordHash, md5: md5 } diff --git a/test/integration/connection/test-helper.js b/test/integration/connection/test-helper.js index 813d6041..99661a46 100644 --- a/test/integration/connection/test-helper.js +++ b/test/integration/connection/test-helper.js @@ -21,9 +21,7 @@ var connect = function (callback) { con.password(helper.args.password) }) con.once('authenticationMD5Password', function (msg) { - var inner = utils.md5(helper.args.password + helper.args.user) - var outer = utils.md5(Buffer.concat([Buffer.from(inner), msg.salt])) - con.password('md5' + outer) + con.password(utils.postgresMd5PasswordHash(helper.args.user, helper.args.password, msg.salt)); }) con.once('readyForQuery', function () { con.query('create temp table ids(id integer)') diff --git a/test/unit/client/md5-password-tests.js b/test/unit/client/md5-password-tests.js index 26e233ed..85b357ae 100644 --- a/test/unit/client/md5-password-tests.js +++ b/test/unit/client/md5-password-tests.js @@ -11,9 +11,7 @@ test('md5 authentication', function () { test('responds', function () { assert.lengthIs(client.connection.stream.packets, 1) test('should have correct encrypted data', function () { - var encrypted = utils.md5(client.password + client.user) - encrypted = utils.md5(encrypted + salt.toString('binary')) - var password = 'md5' + encrypted + var password = utils.postgresMd5PasswordHash(client.user, client.password, salt) // how do we want to test this? assert.equalBuffers(client.connection.stream.packets[0], new BufferList() .addCString(password).join(true, 'p'))