Module
MySQL client for Deno with focus on performance. Supports prepared statements, non-utf8 encodings, binary log protocol, compression much more
Very Popular
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112/*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)*/
import { Buffer, createHash,} from "../deps.ts";
function sha1(msg: Buffer|string, msg1?: Buffer|string, msg2?: Buffer|string) { const hash = createHash('sha1'); hash.update(msg); if (msg1) { hash.update(msg1); }
if (msg2) { hash.update(msg2); }
return hash.digest() as Buffer;}
export function xor(a: Buffer|string, b: Buffer|string) { if (!Buffer.isBuffer(a)) { a = Buffer.from(a, 'binary'); }
if (!Buffer.isBuffer(b)) { b = Buffer.from(b, 'binary'); }
const result = Buffer.allocUnsafe(a.length);
for (let i = 0; i < a.length; i++) { result[i] = a[i] ^ b[i]; } return result;}
function token(password: string, scramble1: Buffer, scramble2: Buffer) { // TODO: use buffers (not sure why strings here) if (!password) { return Buffer.alloc(0); } const stage1 = sha1(password); return calculateTokenFromPasswordSha(stage1, scramble1, scramble2);}
export function calculateTokenFromPasswordSha( passwordSha: Buffer|string, scramble1: Buffer, scramble2: Buffer,) { // 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); return xor(stage3, passwordSha);}
export const calculateToken = token;
export function verifyToken(publicSeed1: string | Buffer, publicSeed2: string | Buffer, token: string | Buffer, doubleSha: string | Buffer) { const hashStage1 = xor(token, sha1(publicSeed1, publicSeed2, doubleSha)); const candidateHash2 = sha1(hashStage1); return candidateHash2.compare(Buffer.from(doubleSha)) === 0;}
export function doubleSha1(password: string) { return sha1(sha1(password));}
export function xorRotating(a: string | Buffer, seed: string | Buffer) { if (!Buffer.isBuffer(a)) { a = Buffer.from(a, 'binary'); }
if (!Buffer.isBuffer(seed)) { seed = Buffer.from(seed, 'binary'); }
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;}