Skip to content

Commit

Permalink
test1
Browse files Browse the repository at this point in the history
  • Loading branch information
shiyuhang0 committed Sep 1, 2023
1 parent 48c2b8d commit 69e5ad1
Show file tree
Hide file tree
Showing 12 changed files with 438 additions and 87 deletions.
30 changes: 9 additions & 21 deletions lib/auth_41.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,7 @@
server stores sha1(sha1(password)) ( hash_stag2)
*/

const crypto = require('crypto');

function sha1(msg, msg1, msg2) {
const hash = crypto.createHash('sha1');
hash.update(msg);
if (msg1) {
hash.update(msg1);
}

if (msg2) {
hash.update(msg2);
}

return hash.digest();
}
const crypto = require('./crypto/utils')

function xor(a, b) {
const result = Buffer.allocUnsafe(a.length);
Expand All @@ -54,7 +40,7 @@ function token(password, scramble1, scramble2) {
if (!password) {
return Buffer.alloc(0);
}
const stage1 = sha1(password);
const stage1 = crypto.sha1(password);
return exports.calculateTokenFromPasswordSha(stage1, scramble1, scramble2);
}

Expand All @@ -66,21 +52,23 @@ exports.calculateTokenFromPasswordSha = function(
// we use AUTH 41 here, and we need only the bytes we just need.
const authPluginData1 = scramble1.slice(0, 8);
const authPluginData2 = scramble2.slice(0, 12);
const stage2 = sha1(passwordSha);
const stage3 = sha1(authPluginData1, authPluginData2, stage2);
const stage2 = crypto.sha1(passwordSha);
const stage3 = crypto.sha1(authPluginData1, authPluginData2, stage2);
console.log('stage3', stage3.length)
console.log('passwordSha', passwordSha.length)
return xor(stage3, passwordSha);
};

exports.calculateToken = token;

exports.verifyToken = function(publicSeed1, publicSeed2, token, doubleSha) {
const hashStage1 = xor(token, sha1(publicSeed1, publicSeed2, doubleSha));
const candidateHash2 = sha1(hashStage1);
const hashStage1 = xor(token, crypto.sha1(publicSeed1, publicSeed2, doubleSha));
const candidateHash2 = crypto.sha1(hashStage1);
return candidateHash2.compare(doubleSha) === 0;
};

exports.doubleSha1 = function(password) {
return sha1(sha1(password));
return crypto.sha1(crypto.sha1(password));
};

function xorRotating(a, seed) {
Expand Down
27 changes: 7 additions & 20 deletions lib/auth_plugins/caching_sha2_password.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
// https://mysqlserverteam.com/mysql-8-0-4-new-default-authentication-plugin-caching_sha2_password/

const PLUGIN_NAME = 'caching_sha2_password';
const crypto = require('crypto');
const { xor, xorRotating } = require('../auth_41');
const crypto = require('../crypto/utils')

const { xor } = require('../auth_41');

const REQUEST_SERVER_KEY_PACKET = Buffer.from([2]);
const FAST_AUTH_SUCCESS_PACKET = Buffer.from([3]);
Expand All @@ -15,38 +16,24 @@ const STATE_TOKEN_SENT = 1;
const STATE_WAIT_SERVER_KEY = 2;
const STATE_FINAL = -1;

function sha256(msg) {
const hash = crypto.createHash('sha256');
hash.update(msg);
return hash.digest();
}

function calculateToken(password, scramble) {
if (!password) {
return Buffer.alloc(0);
}
const stage1 = sha256(Buffer.from(password));
const stage2 = sha256(stage1);
const stage3 = sha256(Buffer.concat([stage2, scramble]));
const stage1 = crypto.sha256(Buffer.from(password));
const stage2 = crypto.sha256(stage1);
const stage3 = crypto.sha256(Buffer.concat([stage2, scramble]));
return xor(stage1, stage3);
}

function encrypt(password, scramble, key) {
const stage1 = xorRotating(
Buffer.from(`${password}\0`, 'utf8'),
scramble
);
return crypto.publicEncrypt(key, stage1);
}

module.exports = (pluginOptions = {}) => ({ connection }) => {
let state = 0;
let scramble = null;

const password = connection.config.password;

const authWithKey = serverKey => {
const _password = encrypt(password, scramble, serverKey);
const _password = crypto.encrypt(password, scramble, serverKey);
state = STATE_FINAL;
return _password;
};
Expand Down
13 changes: 2 additions & 11 deletions lib/auth_plugins/sha256_password.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,22 @@
'use strict';

const PLUGIN_NAME = 'sha256_password';
const crypto = require('crypto');
const { xorRotating } = require('../auth_41');
const crypto = require('../crypto/utils')

const REQUEST_SERVER_KEY_PACKET = Buffer.from([1]);

const STATE_INITIAL = 0;
const STATE_WAIT_SERVER_KEY = 1;
const STATE_FINAL = -1;

function encrypt(password, scramble, key) {
const stage1 = xorRotating(
Buffer.from(`${password}\0`, 'utf8'),
scramble
);
return crypto.publicEncrypt(key, stage1);
}

module.exports = (pluginOptions = {}) => ({ connection }) => {
let state = 0;
let scramble = null;

const password = connection.config.password;

const authWithKey = serverKey => {
const _password = encrypt(password, scramble, serverKey);
const _password = crypto.encrypt(password, scramble, serverKey);
state = STATE_FINAL;
return _password;
};
Expand Down
17 changes: 3 additions & 14 deletions lib/commands/client_handshake.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const Packets = require('../packets/index.js');
const ClientConstants = require('../constants/client.js');
const CharsetToEncoding = require('../constants/charset_encodings.js');
const auth41 = require('../auth_41.js');
const {secureStream} = require('../stream.js');

function flagNames(flags) {
const res = [];
Expand Down Expand Up @@ -146,21 +147,9 @@ class ClientHandshake extends Command {
// send ssl upgrade request and immediately upgrade connection to secure
this.clientFlags |= ClientConstants.SSL;
this.sendSSLRequest(connection);
connection.startTLS(err => {
// after connection is secure
if (err) {
// SSL negotiation error are fatal
err.code = 'HANDSHAKE_SSL_ERROR';
err.fatal = true;
this.emit('error', err);
return;
}
// rest of communication is encrypted
this.sendCredentials(connection);
});
} else {
this.sendCredentials(connection);
secureStream(connection)
}
this.sendCredentials(connection);
if (multiFactorAuthentication) {
// if the server supports multi-factor authentication, we enable it in
// the client
Expand Down
27 changes: 12 additions & 15 deletions lib/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

'use strict';

const Net = require('net');
const Tls = require('tls');
const Timers = require('timers');
const EventEmitter = require('events').EventEmitter;
Expand All @@ -29,6 +28,7 @@ const Packets = require('./packets/index.js');
const Commands = require('./commands/index.js');
const ConnectionConfig = require('./connection_config.js');
const CharsetToEncoding = require('./constants/charset_encodings.js');
const {getStream} = require("./stream");

let _connectionId = 0;

Expand All @@ -44,14 +44,11 @@ class Connection extends EventEmitter {
// TODO: use `/usr/local/mysql/bin/mysql_config --socket` output? as default socketPath
// if there is no host/port and no socketPath parameters?
if (!opts.config.stream) {
this.stream = getStream(opts.config.ssl);
if (opts.config.socketPath) {
this.stream = Net.connect(opts.config.socketPath);
this.stream.connect(opts.config.socketPath);
} else {
this.stream = Net.connect(
opts.config.port,
opts.config.host
);

this.stream.connect(opts.config.port, opts.config.host)
// Optionally enable keep-alive on the socket.
if (this.config.enableKeepAlive) {
this.stream.on('connect', () => {
Expand Down Expand Up @@ -146,13 +143,13 @@ class Connection extends EventEmitter {
// most common example: "Too many connections" error ( packet is sent immediately on connection attempt, we don't know server encoding yet)
// will be overwritten with actual encoding value as soon as server handshake packet is received
this.serverEncoding = 'utf8';
if (this.config.connectTimeout) {
const timeoutHandler = this._handleTimeoutError.bind(this);
this.connectTimeout = Timers.setTimeout(
timeoutHandler,
this.config.connectTimeout
);
}
// if (this.config.connectTimeout) {
// const timeoutHandler = this._handleTimeoutError.bind(this);
// this.connectTimeout = Timers.setTimeout(
// timeoutHandler,
// this.config.connectTimeout
// );
// }
}

promise(promiseImpl) {
Expand Down Expand Up @@ -408,7 +405,7 @@ class Connection extends EventEmitter {
err.code = code || 'PROTOCOL_ERROR';
this.emit('error', err);
}

get fatalError() {
return this._fatalError;
}
Expand Down
69 changes: 69 additions & 0 deletions lib/crypto/utils-legacy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
'use strict'
// This file contains crypto utility functions for versions of Node.js < 15.0.0,
// which does not support the WebCrypto.subtle API.

const nodeCrypto = require('crypto')

function md5(string) {
return nodeCrypto.createHash('md5').update(string, 'utf-8').digest('hex')
}

// See AuthenticationMD5Password at https://www.postgresql.org/docs/current/static/protocol-flow.html
function postgresMd5PasswordHash(user, password, salt) {
const inner = md5(password + user);
const outer = md5(Buffer.concat([Buffer.from(inner), salt]));
return `md5${outer}`
}

function sha256(text) {
return nodeCrypto.createHash('sha256').update(text).digest()
}

function sha1(msg,msg1,msg2) {
const hash = nodeCrypto.createHash('sha1');
hash.update(msg);
if (msg1) {
hash.update(msg1);
}
if (msg2) {
hash.update(msg2);
}
return hash.digest();
}

function xorRotating(a, seed) {
const result = Buffer.allocUnsafe(a.length);
const seedLen = seed.length;

for (let i = 0; i < a.length; i++) {
result[i] = a[i] ^ seed[i % seedLen];
}
return result;
}

function encrypt(password, scramble, key) {
const stage1 = xorRotating(
Buffer.from(`${password}\0`, 'utf8'),
scramble
);
return nodeCrypto.publicEncrypt(key, stage1);
}

function hmacSha256(key, msg) {
return nodeCrypto.createHmac('sha256', key).update(msg).digest()
}

function deriveKey(password, salt, iterations) {
return nodeCrypto.pbkdf2Sync(password, salt, iterations, 32, 'sha256')
}

module.exports = {
postgresMd5PasswordHash,
randomBytes: nodeCrypto.randomBytes,
deriveKey,
sha256,
hmacSha256,
md5,
sha1,
encrypt,
}
Loading

0 comments on commit 69e5ad1

Please sign in to comment.