mysql2
Version:
fast mysql driver. Implements core protocol, prepared statements, ssl and compression in native JS
86 lines (65 loc) • 2.18 kB
JavaScript
/*
4.1 authentication: (http://bazaar.launchpad.net/~mysql/mysql-server/5.5/view/head:/sql/password.c)
SERVER: public_seed=create_random_string()
send(public_seed)
CLIENT: recv(public_seed)
hash_stage1=sha1("password")
hash_stage2=sha1(hash_stage1)
reply=xor(hash_stage1, sha1(public_seed,hash_stage2)
// this three steps are done in scramble()
send(reply)
SERVER: recv(reply)
hash_stage1=xor(reply, sha1(public_seed,hash_stage2))
candidate_hash2=sha1(hash_stage1)
check(candidate_hash2==hash_stage2)
server stores sha1(sha1(password)) ( hash_stag2)
*/
var crypto = require('crypto');
var Buffer = require('safe-buffer').Buffer;
function sha1 (msg, msg1, msg2) {
var hash = crypto.createHash('sha1');
hash.update(msg);
if (msg1) {
hash.update(msg1);
}
if (msg2) {
hash.update(msg2);
}
return hash.digest();
}
function xor (a, b) {
if (!Buffer.isBuffer(a)) {
a = Buffer.from(a, 'binary');
}
if (!Buffer.isBuffer(b)) {
b = Buffer.from(b, 'binary');
}
var result = Buffer.allocUnsafe(a.length);
for (var i = 0; i < a.length; i++) {
result[i] = (a[i] ^ b[i]);
}
return result;
}
function token (password, scramble1, scramble2) {
// TODO: use buffers (not sure why strings here)
if (!password) {
return Buffer.alloc(0);
}
var stage1 = sha1(password);
return module.exports.calculateTokenFromPasswordSha(stage1, scramble1, scramble2);
}
module.exports.calculateTokenFromPasswordSha = function (passwordSha, scramble1, scramble2) {
var stage2 = sha1(passwordSha);
var stage3 = sha1(scramble1, scramble2, stage2);
return xor(stage3, passwordSha);
};
module.exports.calculateToken = token;
module.exports.verifyToken = function (publicSeed1, publicSeed2, token, doubleSha) {
var hashStage1 = xor(token, sha1(publicSeed1, publicSeed2, doubleSha));
var candidateHash2 = sha1(hashStage1);
// TODO better way to compare buffers?
return candidateHash2.toString('hex') == doubleSha.toString('hex');
};
module.exports.doubleSha1 = function (password) {
return sha1(sha1(password));
};