@tgsnake/core
Version:
Pure Telegram MTProto library for nodejs
124 lines (123 loc) • 5.23 kB
JavaScript
;
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();
}