Skip to content

Instantly share code, notes, and snippets.

@dannycoates
Last active December 18, 2015 23:49
Show Gist options
  • Save dannycoates/5864047 to your computer and use it in GitHub Desktop.
Save dannycoates/5864047 to your computer and use it in GitHub Desktop.
SRP test client
var crypto = require('crypto');
var config = require('../lib/config').get('srp');
var srp = require('../lib/srp');
var srpParams = require('../lib/srp_group_params');
var util = require('../lib/util');
var bigint = require('bigint');
var request = require('request');
var alg = config.alg_name;
var N = srpParams[config.N_bits].N;
var generator = srpParams[config.N_bits].g;
var saltBytes = config.s_bytes;
var baseUrl = 'http://localhost:9000/';
function Client(email, password) {
this.email = email;
this.password = password;
this.sessionId = null;
this.K = null;
}
Client.prototype.create = function (cb) {
var salt = crypto.randomBytes(saltBytes);
var verifier = srp.getv(salt, this.email, this.password, N, generator, alg);
request(
{
method: 'POST',
url: baseUrl + 'create',
json: {
email: this.email,
verifier: verifier.toString(16),
salt: salt.toString('hex'),
params: {
alg: alg,
N_bits: config.N_bits
}
}
},
function (err, res, json) {
cb(err, json);
}
);
};
Client.prototype.login = function (cb) {
request(
{
method: 'POST',
url: baseUrl + 'startLogin',
json: {
email: this.email
}
},
function (err, res, json) {
var a = bigint.fromBuffer(crypto.randomBytes(saltBytes));
var g = srpParams[json.srp.N_bits].g;
var N = srpParams[json.srp.N_bits].N;
var A = srp.getA(g, a, N);
var B = bigint(json.srp.B, 16);
var S = srp.client_getS(
Buffer(json.srp.s, 'hex'),
this.email,
this.password,
N,
g,
a,
B,
json.srp.alg
);
var M = srp.getM(A, B, S);
this.sessionId = json.sessionId;
this.K = srp.getK(S, alg).toBuffer();
request(
{
method: 'POST',
url: baseUrl + 'finishLogin',
json: {
sessionId: json.sessionId,
A: A.toString(16),
M: M.toString(16)
}
},
function _decryptLoginResponse(err, res, json) {
if (err) {
return cb(err);
}
util.srpResponseKeys(this.K, function (err, keys) {
var blob = Buffer(json.bundle, 'base64');
var cyphertext = blob.slice(0, blob.length - 32);
var hmac = blob.slice(blob.length - 32, blob.length);
var check = crypto.createHmac('sha256', keys.respHMACkey);
check.update(cyphertext);
if (hmac.toString('hex') !== check.digest('hex')) {
return cb(new Error("Corrupted Message"));
}
var cleartext = bigint.fromBuffer(cyphertext)
.xor(bigint.fromBuffer(keys.respXORkey))
.toBuffer();
var result = {
kA: cleartext.slice(0, 32).toString('base64'),
wrapKb: cleartext.slice(32, 64).toString('base64'),
signToken: cleartext.slice(64).toString('hex')
};
cb(null, result);
});
}.bind(this)
);
}.bind(this)
);
};
//Test
var email = "[email protected]";
var password = "somePassword";
var slt = crypto.randomBytes(32);
var v = srp.getv(slt, email, password, N, generator, alg);
var a = bigint.fromBuffer(crypto.randomBytes(32));
var b = bigint.fromBuffer(crypto.randomBytes(32));
var A = srp.getA(generator, a, N);
var B = srp.getB(v, generator, b, N, alg);
var Sa = srp.client_getS(slt, email, password, N, generator, a, B, alg);
var Sb = srp.server_getS(slt, v, N, generator, A, b, alg);
console.log("Sane? %s", Sa.toString(16) === Sb.toString(16));
var c = new Client('[email protected]', 'somePassword');
c.create(function (err, json) {
console.log(json);
c.login(console.log);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment