@tgsnake/core
Version:
Pure Telegram MTProto library for nodejs
93 lines (92 loc) • 2.94 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.xor = xor;
exports.computePasswordHash = computePasswordHash;
exports.computePasswordCheck = computePasswordCheck;
const index_js_1 = require("../raw/index.js");
const platform_node_js_1 = require("../platform.node.js");
const helpers_js_1 = require("../helpers.js");
function sha256(data) {
return platform_node_js_1.crypto.createHash('sha256').update(data).digest();
}
function xor(a, b) {
const length = Math.min(platform_node_js_1.Buffer.byteLength(a), platform_node_js_1.Buffer.byteLength(b));
for (let i = 0; i < length; i++) {
a[i] =
a[i] ^ b[i];
}
return a;
}
function computePasswordHash(algo, password) {
const hash1 = sha256(platform_node_js_1.Buffer.concat([
algo.salt1,
platform_node_js_1.Buffer.from(password, 'utf8'),
algo.salt1,
]));
const hash2 = sha256(platform_node_js_1.Buffer.concat([
algo.salt2,
hash1,
algo.salt2,
]));
const hash3 = platform_node_js_1.crypto.pbkdf2Sync(hash2, algo.salt1, 100000, 64, 'sha512');
return sha256(platform_node_js_1.Buffer.concat([
algo.salt2,
hash3,
algo.salt2,
]));
}
function computePasswordCheck(r, password) {
const algo = r.currentAlgo;
const pBytes = algo.p;
const p = btoi(pBytes);
const g = algo.g;
const gBytes = itob(BigInt(g));
const BBytes = r.srpB;
const B = btoi(BBytes);
const srpId = r.srpId;
const xBytes = computePasswordHash(algo, password);
const x = btoi(xBytes);
const gX = (0, helpers_js_1.bigIntPow)(BigInt(g), x, p);
const kBytes = sha256(platform_node_js_1.Buffer.concat([pBytes, gBytes]));
const k = btoi(kBytes);
const kGX = (0, helpers_js_1.bigIntMod)(k * gX, p);
let aBytes;
let a;
let A;
let ABytes;
let u;
while (true) {
aBytes = platform_node_js_1.crypto.randomBytes(256);
a = btoi(aBytes);
A = (0, helpers_js_1.bigIntPow)(BigInt(g), a, p);
ABytes = itob(A);
u = btoi(sha256(platform_node_js_1.Buffer.concat([ABytes, BBytes])));
if (u > BigInt(0))
break;
}
const gB = (0, helpers_js_1.bigIntMod)(B - kGX, p);
const uX = u * x;
const aUX = a + uX;
const S = (0, helpers_js_1.bigIntPow)(gB, aUX, p);
const SBytes = itob(S);
const KBytes = sha256(SBytes);
const M1Bytes = sha256(platform_node_js_1.Buffer.concat([
xor(sha256(pBytes), sha256(gBytes)),
sha256(algo.salt1),
sha256(algo.salt2),
ABytes,
BBytes,
KBytes,
]));
return new index_js_1.Raw.InputCheckPasswordSRP({
srpId: srpId,
a: ABytes,
m1: M1Bytes,
});
}
function btoi(b) {
return (0, helpers_js_1.bufferToBigint)(b, false);
}
function itob(i) {
return (0, helpers_js_1.bigintToBuffer)(i, 256, false);
}