From 553994d375a91ef1c05b464e77806b0e1a767448 Mon Sep 17 00:00:00 2001 From: John Papandriopoulos Date: Mon, 18 Sep 2017 01:41:13 -0700 Subject: [PATCH] Support for SHA auth algorithms --- lib/auth.js | 43 +++++++++++++++++++++++++++---------------- lib/helpers.js | 10 ++++++++++ 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/lib/auth.js b/lib/auth.js index 42f9adaec..8928e5f17 100644 --- a/lib/auth.js +++ b/lib/auth.js @@ -5,6 +5,8 @@ var uuid = require('uuid') var helpers = require('./helpers') var md5 = helpers.md5 +var sha1 = helpers.sha1 +var sha256 = helpers.sha256 var toBase64 = helpers.toBase64 function Auth (request) { @@ -71,30 +73,39 @@ Auth.prototype.digest = function (method, path, authHeader) { } /** - * RFC 2617: handle both MD5 and MD5-sess algorithms. - * - * If the algorithm directive's value is "MD5" or unspecified, then HA1 is - * HA1=MD5(username:realm:password) - * If the algorithm directive's value is "MD5-sess", then HA1 is - * HA1=MD5(MD5(username:realm:password):nonce:cnonce) + * RFC 2617: handle MD5, MD5-SESS, SHA, SHA-256 algorithms. */ - var ha1Compute = function (algorithm, user, realm, pass, nonce, cnonce) { - var ha1 = md5(user + ':' + realm + ':' + pass) - if (algorithm && algorithm.toLowerCase() === 'md5-sess') { - return md5(ha1 + ':' + nonce + ':' + cnonce) - } else { - return ha1 + var hashFunction = function (algorithm) { + if (algorithm === undefined) { + algorithm = 'MD5' + } + switch (algorithm.toUpperCase()) { + case 'SHA': + return sha1 + case 'SHA-256': + return sha256 + default: + case 'MD5': + case 'MD5-SESS': + return md5 } } var qop = /(^|,)\s*auth\s*($|,)/.test(challenge.qop) && 'auth' var nc = qop && '00000001' var cnonce = qop && uuid().replace(/-/g, '') - var ha1 = ha1Compute(challenge.algorithm, self.user, challenge.realm, self.pass, challenge.nonce, cnonce) - var ha2 = md5(method + ':' + path) + + var hash = hashFunction(challenge.algorithm) + var a1 = self.user + ':' + challenge.realm + ':' + self.pass + var ha1 = hash(a1) + if (challenge.algorithm && challenge.algorithm.toUpperCase() === 'MD5-SESS') { + ha1 = hash(ha1 + ':' + challenge.nonce + ':' + cnonce) + } + var ha2 = hash(method + ':' + path) + var digestResponse = qop - ? md5(ha1 + ':' + challenge.nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + ha2) - : md5(ha1 + ':' + challenge.nonce + ':' + ha2) + ? hash(ha1 + ':' + challenge.nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + ha2) + : hash(ha1 + ':' + challenge.nonce + ':' + ha2) var authValues = { username: self.user, realm: challenge.realm, diff --git a/lib/helpers.js b/lib/helpers.js index 8b2a7e6eb..ab2eb12cc 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -31,6 +31,14 @@ function md5 (str) { return crypto.createHash('md5').update(str).digest('hex') } +function sha1 (str) { + return crypto.createHash('sha1').update(str).digest('hex') +} + +function sha256 (str) { + return crypto.createHash('sha256').update(str).digest('hex') +} + function isReadStream (rs) { return rs.readable && rs.path && rs.mode } @@ -59,6 +67,8 @@ function version () { exports.paramsHaveRequestBody = paramsHaveRequestBody exports.safeStringify = safeStringify exports.md5 = md5 +exports.sha1 = sha1 +exports.sha256 = sha256 exports.isReadStream = isReadStream exports.toBase64 = toBase64 exports.copy = copy