UNPKG

@tgsnake/core

Version:

Pure Telegram MTProto library for nodejs

124 lines (123 loc) 5.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TCPIntermediateO = void 0; const tcp_js_1 = require("./tcp.js"); const helpers_js_1 = require("../../helpers.js"); const platform_node_js_1 = require("../../platform.node.js"); const Aes_js_1 = require("../../crypto/Aes.js"); const index_js_1 = require("../../raw/core/index.js"); class TCPIntermediateO extends tcp_js_1.TCP { _reserved; _encryptor; _decryptor; constructor() { super(); this._reserved = [ platform_node_js_1.Buffer.from('HEAD'), platform_node_js_1.Buffer.from('POST'), platform_node_js_1.Buffer.from('GET'), platform_node_js_1.Buffer.from('OPTI'), platform_node_js_1.Buffer.from('eeeeeeee', 'hex'), ]; } async connect(ip, port, proxy, dcId) { await super.connect(ip, port, proxy, dcId); let nonce; if (proxy && 'secret' in proxy && 'port' in proxy && 'server' in proxy && dcId) { let secret = typeof proxy.secret === 'string' ? (0, helpers_js_1.normalizeSecretString)(proxy.secret) : platform_node_js_1.Buffer.from(proxy.secret); secret = platform_node_js_1.Buffer.byteLength(secret) === 17 && secret[0] === 0xdd ? secret.subarray(1) : secret; while (true) { nonce = platform_node_js_1.crypto.randomBytes(64); if (!platform_node_js_1.Buffer.from([nonce[0]]).equals(platform_node_js_1.Buffer.from('ef', 'hex')) && !(0, helpers_js_1.includesBuffer)(this._reserved, nonce) && !nonce.subarray(4, 8).equals(platform_node_js_1.Buffer.alloc(4))) { nonce[56] = nonce[57] = nonce[58] = nonce[59] = 0xee; break; } } const temp = (0, helpers_js_1.sliceBuffer)(nonce, 55, 7, -1); const encryptionKey = sha256(platform_node_js_1.Buffer.concat([ nonce.subarray(8, 40), secret, ])); const encryptionIv = nonce.subarray(40, 56); const decryptionIv = sha256(platform_node_js_1.Buffer.concat([ temp.subarray(0, 32), secret, ])); const decryptionKey = temp.subarray(32, 48); this._encryptor = (0, Aes_js_1.ctr256Cipher)(encryptionKey, encryptionIv); this._decryptor = (0, Aes_js_1.ctr256Cipher)(decryptionKey, decryptionIv); const _dcId = platform_node_js_1.Buffer.alloc(2); _dcId.writeInt8(dcId, 0); nonce = platform_node_js_1.Buffer.concat([ nonce.subarray(0, 60), _dcId, nonce.subarray(62), ]); nonce = platform_node_js_1.Buffer.concat([ nonce.subarray(0, 56), this._encryptor(nonce).subarray(56, 64), ]); } else { while (true) { nonce = platform_node_js_1.crypto.randomBytes(64); if (!platform_node_js_1.Buffer.from([nonce[0]]).equals(platform_node_js_1.Buffer.from('ef', 'hex')) && !(0, helpers_js_1.includesBuffer)(this._reserved, nonce) && !nonce.subarray(4, 8).equals(platform_node_js_1.Buffer.alloc(4))) { nonce[56] = nonce[57] = nonce[58] = nonce[59] = 0xee; break; } } const temp = (0, helpers_js_1.sliceBuffer)(nonce, 55, 7, -1); const encryptionKey = nonce.subarray(8, 40); const encryptionIv = nonce.subarray(40, 56); const decryptionKey = temp.subarray(0, 32); const decryptionIv = temp.subarray(32, 48); this._encryptor = (0, Aes_js_1.ctr256Cipher)(encryptionKey, encryptionIv); this._decryptor = (0, Aes_js_1.ctr256Cipher)(decryptionKey, decryptionIv); nonce = platform_node_js_1.Buffer.concat([ nonce.subarray(0, 56), this._encryptor(nonce).subarray(56, 64), ]); } await super.send(nonce); } async send(data) { const payload = this._encryptor(platform_node_js_1.Buffer.concat([ index_js_1.Primitive.Int.write(platform_node_js_1.Buffer.byteLength(data)), data, ])); return await super.send(payload); } async recv(_length = 0) { let length = await super.recv(4); if (!length) return; length = this._decryptor(length); const data = await super.recv(length.readInt32LE(0)); if (!data) return; return this._decryptor(data); } } exports.TCPIntermediateO = TCPIntermediateO; function sha256(data) { const hash = platform_node_js_1.crypto.createHash('sha256'); hash.update(data); return hash.digest(); }