auth_41.js 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /*
  2. 4.1 authentication: (http://bazaar.launchpad.net/~mysql/mysql-server/5.5/view/head:/sql/password.c)
  3. SERVER: public_seed=create_random_string()
  4. send(public_seed)
  5. CLIENT: recv(public_seed)
  6. hash_stage1=sha1("password")
  7. hash_stage2=sha1(hash_stage1)
  8. reply=xor(hash_stage1, sha1(public_seed,hash_stage2)
  9. // this three steps are done in scramble()
  10. send(reply)
  11. SERVER: recv(reply)
  12. hash_stage1=xor(reply, sha1(public_seed,hash_stage2))
  13. candidate_hash2=sha1(hash_stage1)
  14. check(candidate_hash2==hash_stage2)
  15. server stores sha1(sha1(password)) ( hash_stag2)
  16. */
  17. var crypto = require('crypto');
  18. function sha1(msg, msg1, msg2) {
  19. var hash = crypto.createHash('sha1');
  20. hash.update(msg);
  21. if (msg1)
  22. hash.update(msg1);
  23. if (msg2)
  24. hash.update(msg2);
  25. return hash.digest();
  26. }
  27. function xor(a, b) {
  28. if (!Buffer.isBuffer(a))
  29. a = new Buffer(a, 'binary');
  30. if (!Buffer.isBuffer(b))
  31. b = new Buffer(b, 'binary');
  32. var result = new Buffer(a.length);
  33. for (var i = 0; i < a.length; i++) {
  34. result[i] = (a[i] ^ b[i]);
  35. }
  36. return result;
  37. }
  38. function token(password, scramble1, scramble2) {
  39. // TODO: use buffers (not sure why strings here)
  40. if (!password) {
  41. return new Buffer(0);
  42. }
  43. var stage1 = sha1(password);
  44. return module.exports.calculateTokenFromPasswordSha(stage1, scramble1, scramble2);
  45. }
  46. module.exports.calculateTokenFromPasswordSha = function(passwordSha, scramble1, scramble2) {
  47. var stage2 = sha1(passwordSha);
  48. var stage3 = sha1(scramble1, scramble2, stage2);
  49. return xor(stage3, passwordSha);
  50. };
  51. module.exports.calculateToken = token;
  52. module.exports.verifyToken = function(publicSeed1, publicSeed2, token, doubleSha) {
  53. var hashStage1 =xor(token, sha1(publicSeed1, publicSeed2, doubleSha));
  54. var candidateHash2 = sha1(hashStage1);
  55. // TODO better way to compare buffers?
  56. return candidateHash2.toString('hex') == doubleSha.toString('hex');
  57. }
  58. module.exports.doubleSha1 = function(password) {
  59. return sha1(sha1(password));
  60. }