Auth.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. var Buffer = require('safe-buffer').Buffer;
  2. var Crypto = require('crypto');
  3. var Auth = exports;
  4. function auth(name, data, options) {
  5. options = options || {};
  6. switch (name) {
  7. case 'mysql_native_password':
  8. return Auth.token(options.password, data.slice(0, 20));
  9. default:
  10. return undefined;
  11. }
  12. }
  13. Auth.auth = auth;
  14. function sha1(msg) {
  15. var hash = Crypto.createHash('sha1');
  16. hash.update(msg, 'binary');
  17. return hash.digest('binary');
  18. }
  19. Auth.sha1 = sha1;
  20. function xor(a, b) {
  21. a = Buffer.from(a, 'binary');
  22. b = Buffer.from(b, 'binary');
  23. var result = Buffer.allocUnsafe(a.length);
  24. for (var i = 0; i < a.length; i++) {
  25. result[i] = (a[i] ^ b[i]);
  26. }
  27. return result;
  28. }
  29. Auth.xor = xor;
  30. Auth.token = function(password, scramble) {
  31. if (!password) {
  32. return Buffer.alloc(0);
  33. }
  34. // password must be in binary format, not utf8
  35. var stage1 = sha1((Buffer.from(password, 'utf8')).toString('binary'));
  36. var stage2 = sha1(stage1);
  37. var stage3 = sha1(scramble.toString('binary') + stage2);
  38. return xor(stage3, stage1);
  39. };
  40. // This is a port of sql/password.c:hash_password which needs to be used for
  41. // pre-4.1 passwords.
  42. Auth.hashPassword = function(password) {
  43. var nr = [0x5030, 0x5735];
  44. var add = 7;
  45. var nr2 = [0x1234, 0x5671];
  46. var result = Buffer.alloc(8);
  47. if (typeof password === 'string'){
  48. password = Buffer.from(password);
  49. }
  50. for (var i = 0; i < password.length; i++) {
  51. var c = password[i];
  52. if (c === 32 || c === 9) {
  53. // skip space in password
  54. continue;
  55. }
  56. // nr^= (((nr & 63)+add)*c)+ (nr << 8);
  57. // nr = xor(nr, add(mul(add(and(nr, 63), add), c), shl(nr, 8)))
  58. nr = this.xor32(nr, this.add32(this.mul32(this.add32(this.and32(nr, [0, 63]), [0, add]), [0, c]), this.shl32(nr, 8)));
  59. // nr2+=(nr2 << 8) ^ nr;
  60. // nr2 = add(nr2, xor(shl(nr2, 8), nr))
  61. nr2 = this.add32(nr2, this.xor32(this.shl32(nr2, 8), nr));
  62. // add+=tmp;
  63. add += c;
  64. }
  65. this.int31Write(result, nr, 0);
  66. this.int31Write(result, nr2, 4);
  67. return result;
  68. };
  69. Auth.randomInit = function(seed1, seed2) {
  70. return {
  71. max_value : 0x3FFFFFFF,
  72. max_value_dbl : 0x3FFFFFFF,
  73. seed1 : seed1 % 0x3FFFFFFF,
  74. seed2 : seed2 % 0x3FFFFFFF
  75. };
  76. };
  77. Auth.myRnd = function(r){
  78. r.seed1 = (r.seed1 * 3 + r.seed2) % r.max_value;
  79. r.seed2 = (r.seed1 + r.seed2 + 33) % r.max_value;
  80. return r.seed1 / r.max_value_dbl;
  81. };
  82. Auth.scramble323 = function(message, password) {
  83. if (!password) {
  84. return Buffer.alloc(0);
  85. }
  86. var to = Buffer.allocUnsafe(8);
  87. var hashPass = this.hashPassword(password);
  88. var hashMessage = this.hashPassword(message.slice(0, 8));
  89. var seed1 = this.int32Read(hashPass, 0) ^ this.int32Read(hashMessage, 0);
  90. var seed2 = this.int32Read(hashPass, 4) ^ this.int32Read(hashMessage, 4);
  91. var r = this.randomInit(seed1, seed2);
  92. for (var i = 0; i < 8; i++){
  93. to[i] = Math.floor(this.myRnd(r) * 31) + 64;
  94. }
  95. var extra = (Math.floor(this.myRnd(r) * 31));
  96. for (var i = 0; i < 8; i++){
  97. to[i] ^= extra;
  98. }
  99. return to;
  100. };
  101. Auth.xor32 = function(a, b){
  102. return [a[0] ^ b[0], a[1] ^ b[1]];
  103. };
  104. Auth.add32 = function(a, b){
  105. var w1 = a[1] + b[1];
  106. var w2 = a[0] + b[0] + ((w1 & 0xFFFF0000) >> 16);
  107. return [w2 & 0xFFFF, w1 & 0xFFFF];
  108. };
  109. Auth.mul32 = function(a, b){
  110. // based on this example of multiplying 32b ints using 16b
  111. // http://www.dsprelated.com/showmessage/89790/1.php
  112. var w1 = a[1] * b[1];
  113. var w2 = (((a[1] * b[1]) >> 16) & 0xFFFF) + ((a[0] * b[1]) & 0xFFFF) + (a[1] * b[0] & 0xFFFF);
  114. return [w2 & 0xFFFF, w1 & 0xFFFF];
  115. };
  116. Auth.and32 = function(a, b){
  117. return [a[0] & b[0], a[1] & b[1]];
  118. };
  119. Auth.shl32 = function(a, b){
  120. // assume b is 16 or less
  121. var w1 = a[1] << b;
  122. var w2 = (a[0] << b) | ((w1 & 0xFFFF0000) >> 16);
  123. return [w2 & 0xFFFF, w1 & 0xFFFF];
  124. };
  125. Auth.int31Write = function(buffer, number, offset) {
  126. buffer[offset] = (number[0] >> 8) & 0x7F;
  127. buffer[offset + 1] = (number[0]) & 0xFF;
  128. buffer[offset + 2] = (number[1] >> 8) & 0xFF;
  129. buffer[offset + 3] = (number[1]) & 0xFF;
  130. };
  131. Auth.int32Read = function(buffer, offset){
  132. return (buffer[offset] << 24)
  133. + (buffer[offset + 1] << 16)
  134. + (buffer[offset + 2] << 8)
  135. + (buffer[offset + 3]);
  136. };