From 24a32ff313a888a65fe63a2b5ef8ccba9058540b Mon Sep 17 00:00:00 2001 From: Khaos Tian Date: Tue, 1 Nov 2016 16:36:40 -0700 Subject: [PATCH] HAP Modification. --- lib/params.js | 2 +- lib/srp.js | 66 +++++++++++++++++++++++++++++++++------------------ 2 files changed, 44 insertions(+), 24 deletions(-) diff --git a/lib/params.js b/lib/params.js index 7111a4a..29c9804 100644 --- a/lib/params.js +++ b/lib/params.js @@ -79,7 +79,7 @@ module.exports = { +'BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC' +'E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF'), g: hex('05'), - hash: 'sha256'}, + hash: 'sha512'}, 4096: { N_length_bits: 4096, diff --git a/lib/srp.js b/lib/srp.js index a77de86..6060870 100644 --- a/lib/srp.js +++ b/lib/srp.js @@ -301,49 +301,57 @@ function getK(params, S_buf) { .digest(); }; -function getM1(params, A_buf, B_buf, S_buf) { +function getM1(params, u_buf, s_buf, A_buf, B_buf, K_buf) { + assertIsBuffer(u_buf, params, "identity (I)"); + assertIsBuffer(s_buf, params, "salt (s)") assertIsNBuffer(A_buf, params, "A"); assertIsNBuffer(B_buf, params, "B"); - assertIsNBuffer(S_buf, params, "S"); + assertIsBuffer(K_buf, params, "K"); + + var hN = crypto.createHash(params.hash).update(params.N.toBuffer()).digest(); + var hG = crypto.createHash(params.hash).update(params.g.toBuffer()).digest(); + + for (var i = 0; i < hN.length; i++) + hN[i] ^= hG[i]; + + var hU = crypto.createHash(params.hash).update(u_buf).digest(); + return crypto.createHash(params.hash) - .update(A_buf).update(B_buf).update(S_buf) + .update(hN).update(hU).update(s_buf) + .update(A_buf).update(B_buf).update(K_buf) .digest(); } -function getM2(params, A_buf, M_buf, K_buf) { +function getM2(params, A_buf, M1_buf, K_buf) { assertIsNBuffer(A_buf, params, "A"); - assertIsBuffer(M_buf, "M"); - assertIsBuffer(K_buf, "K"); + assertIsBuffer(M1_buf, params, "M1"); + assertIsBuffer(K_buf, params, "K"); + return crypto.createHash(params.hash) - .update(A_buf).update(M_buf).update(K_buf) + .update(A_buf).update(M1_buf).update(K_buf) .digest(); } function equal(buf1, buf2) { // constant-time comparison. A drop in the ocean compared to our // non-constant-time modexp operations, but still good practice. - var mismatch = buf1.length - buf2.length; - if (mismatch) { - return false; - } - for (var i = 0; i < buf1.length; i++) { - mismatch |= buf1[i] ^ buf2[i]; - } - return mismatch === 0; + return buf1.toString('hex') === buf2.toString('hex'); } function Client(params, salt_buf, identity_buf, password_buf, secret1_buf) { if (!(this instanceof Client)) { return new Client(params, salt_buf, identity_buf, password_buf, secret1_buf); } - assertIsBuffer(salt_buf, "salt (salt)"); + assertIsBuffer(salt_buf, "salt (s)"); assertIsBuffer(identity_buf, "identity (I)"); assertIsBuffer(password_buf, "password (P)"); assertIsBuffer(secret1_buf, "secret1"); this._private = { params: params, k_num: getk(params), x_num: getx(params, salt_buf, identity_buf, password_buf), - a_num: new BigInteger(secret1_buf) }; + a_num: new BigInteger(secret1_buf), + u_buf: identity_buf, + s_buf: salt_buf }; this._private.A_buf = getA(params, this._private.a_num); } @@ -361,6 +369,9 @@ Client.prototype = { p.M2_buf = getM2(p.params, p.A_buf, p.M1_buf, p.K_buf); p.u_num = u_num; // only for tests p.S_buf = S_buf_x; // only for tests + p.B_buf = B_buf; + p.M1_buf = getM1(p.params, p.u_buf, p.s_buf, p.A_buf, p.B_buf, p.K_buf); + p.M2_buf = getM2(p.params, p.A_buf, p.M1_buf, p.K_buf); }, computeM1: function computeM1() { if (this._private.M1_buf === undefined) @@ -378,16 +389,20 @@ Client.prototype = { } }; -function Server(params, verifier_buf, secret2_buf) { +function Server(params, salt_buf, identity_buf, password_buf, secret2_buf) { if (!(this instanceof Server)) { - return new Server(params, verifier_buf, secret2_buf); + return new Server(params, salt_buf, identity_buf, password_buf, secret2_buf); } - assertIsBuffer(verifier_buf, "verifier"); + assertIsBuffer(salt_buf, "salt (salt)"); + assertIsBuffer(identity_buf, "identity (I)"); + assertIsBuffer(password_buf, "password (P)"); assertIsBuffer(secret2_buf, "secret2"); this._private = { params: params, k_num: getk(params), b_num: new BigInteger(secret2_buf), - v_num: new BigInteger(verifier_buf) }; + v_num: new BigInteger(computeVerifier(params, salt_buf, identity_buf, password_buf)), + u_buf: identity_buf, + s_buf: salt_buf }; this._private.B_buf = getB(params, this._private.k_num, this._private.v_num, this._private.b_num); @@ -403,7 +418,7 @@ Server.prototype = { var u_num = getu(p.params, A_buf, p.B_buf); var S_buf = server_getS(p.params, p.v_num, A_num, p.b_num, u_num); p.K_buf = getK(p.params, S_buf); - p.M1_buf = getM1(p.params, A_buf, p.B_buf, S_buf); + p.M1_buf = getM1(p.params, p.u_buf, p.s_buf, A_buf, p.B_buf, p.K_buf); p.M2_buf = getM2(p.params, A_buf, p.M1_buf, p.K_buf); p.u_num = u_num; // only for tests p.S_buf = S_buf; // only for tests @@ -413,12 +428,17 @@ Server.prototype = { throw new Error("incomplete protocol"); if (!equal(this._private.M1_buf, clientM1_buf)) throw new Error("client did not use the same password"); - return this._private.M2_buf; + // return this._private.M2_buf; }, computeK: function computeK() { if (this._private.K_buf === undefined) throw new Error("incomplete protocol"); return this._private.K_buf; + }, + computeM2: function computeM2() { + if (this._private.M2_buf === undefined) + throw new Error("incomplete protocol"); + return this._private.M2_buf; } };