UNPKG

jsrp

Version:

JavaScript SRP implementation

179 lines (153 loc) 5.4 kB
// Generated by CoffeeScript 2.3.2 (function() { var BigInteger, SRP, createHash, parameters, randomBytes, transform; BigInteger = require('jsbn').BigInteger; createHash = require('create-hash'); randomBytes = require('randombytes'); transform = require('./transform'); parameters = require('./parameters'); SRP = class SRP { constructor(length) { this.params = parameters.get(length); } // x = H(s | H(I | ":" | P)) // Returns bigInteger x(options) { var I, P, identifierPasswordHash, result, salt, xHash; // Options expects I, P, and salt property, where I is the identifier // and P is the password. All of these should be buffers. I = options.I; P = options.P; salt = options.salt; identifierPasswordHash = createHash(this.params.hash).update(I).update(Buffer.from(':')).update(P).digest(); xHash = createHash(this.params.hash).update(salt).update(identifierPasswordHash).digest(); result = transform.buffer.toBigInteger(xHash); return result; } // v = g^x % N // Returns Buffer v(options) { var I, P, result, salt; // Expects salt, I, P I = options.I; P = options.P; salt = options.salt; result = this.params.g.modPow(this.x(options), this.params.N); result = transform.pad.toN(result, this.params); return result; } // Returns a random BigInteger a(callback) { return randomBytes(32, function(err, resultBuf) { var result; result = transform.buffer.toBigInteger(resultBuf); return callback(err, result); }); } // Returns a random BigInteger b(callback) { return randomBytes(32, function(err, resultBuf) { var result; result = transform.buffer.toBigInteger(resultBuf); return callback(err, result); }); } // A = g^a % N A(options) { var a, result; // Expects a, which should be a random BigInteger a = options.a; // Check here to ensure that a.length is not smaller than 256 result = this.params.g.modPow(a, this.params.N); result = transform.pad.toN(result, this.params); return result; } // B = (kv + g^b) % N B(options) { var b, result, v; // Expects v, which should be the client verifier BigInteger, and b, // which should be a random BigInteger v = options.v; // BigInteger b = options.b; // BigInteger // This actually ends up being (v + (g^b % N)) % N, this is the way // everyone else is doing it, so it's the way we're gonna do it. result = this.k().multiply(v).add(this.params.g.modPow(b, this.params.N)).mod(this.params.N); result = transform.pad.toN(result, this.params); return result; } // u = H(A | B) // Returns BigInteger u(options) { var A, B, result; // We want A and B, both in buffer format. A = options.A; // Buffer B = options.B; // Buffer result = createHash(this.params.hash).update(A).update(B).digest(); result = transform.buffer.toBigInteger(result); return result; } // Client S calculation, where S = (B - g^x) ^ (a + u * x) % N // Returns Buffer clientS(options) { var B, a, result, u, x; B = options.B; // BigInteger a = options.a; // BigInteger u = options.u; // BigInteger x = options.x; // BigInteger result = B.subtract(this.k().multiply(this.params.g.modPow(x, this.params.N))).modPow(a.add(u.multiply(x)), this.params.N); result = transform.pad.toN(result, this.params); return result; } // S = (A * v^u) ^ b % N serverS(options) { var A, b, result, u, v; A = options.A; // BigInteger v = options.v; // BigInteger u = options.u; // BigInteger b = options.b; // BigInteger result = A.multiply(v.modPow(u, this.params.N)).modPow(b, this.params.N); result = transform.pad.toN(result, this.params); return result; } // SRP-6 multiplier // Returns BigInteger k() { var result; result = createHash(this.params.hash).update(transform.pad.toN(this.params.N, this.params)).update(transform.pad.toN(this.params.g, this.params)).digest(); result = transform.buffer.toBigInteger(result); return result; } K(options) { var S, result; S = options.S; // Buffer result = createHash(this.params.hash).update(S).digest(); return result; } M1(options) { var A, B, K, result; A = options.A; // Buffer B = options.B; // Buffer K = options.K; // Buffer result = createHash(this.params.hash).update(A).update(B).update(K).digest(); return result; } M2(options) { var A, K, M, result; A = options.A; // Buffer M = options.M; // Buffer K = options.K; // Buffer result = createHash(this.params.hash).update(A).update(M).update(K).digest(); return result; } generateSalt(callback) { return randomBytes(32, function(err, resultBuf) { return callback(err, resultBuf); }); } // This is used to ensure that values are not zero when mod N. isZeroWhenModN(thisBigInt) { return thisBigInt.mod(this.params.N).equals(BigInteger.ZERO); } }; module.exports = SRP; }).call(this);