node-query/node_modules/mysql2/lib/auth_41.js

76 lines
2.0 KiB
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');
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 = new Buffer(a, 'binary');
if (!Buffer.isBuffer(b))
b = new Buffer(b, 'binary');
var result = new Buffer(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 new Buffer(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));
}