Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // import {pqPrimeLeemon} from './crypto';
- import { Authorization } from './mtproto';
- import { Subject } from 'rxjs';
- let json;
- let api;
- let mtproto;
- fetch('/mtproto.json').then((it) => {
- it.json().then((answa) => {
- json = {
- constructors: toMap(answa.constructors, 'predicate'),
- constructorIds: toMap(answa.constructors, 'id'),
- constructorTypes: toMap(answa.constructors, 'type'),
- methods: toMap(answa.methods, 'method'),
- };
- window.mtproto = json;
- mtproto = window.mtproto;
- if (!currentDc.authorization.authData.authKeyID) {
- window.json = window.mtproto;
- }
- // sendPlainMessage('req_pq', { nonce: randomBytes(nonce) });
- });
- });
- fetch('/api.json').then((it) => {
- it.json().then((answa) => {
- window.api = {
- constructors: toMap(answa.constructors, 'predicate'),
- constructorIds: toMap(answa.constructors, 'id'),
- constructorTypes: toMap(answa.constructors, 'type'),
- methods: toMap(answa.methods, 'method'),
- };
- api = window.api;
- if (currentDc.authorization.authData.authKeyID) {
- window.json = window.api;
- }
- // sendPlainMessage('req_pq', { nonce: randomBytes(nonce) });
- });
- });
- export class DataCenter {
- seqNo = 0;
- authorization;
- socketConnection: WebSocket;
- isConnecting = true;
- initConnection = false;
- sendCode = false;
- sessionID;
- prevSessionID;
- cipher;
- decipher;
- lastMessageID = [0, 0];
- timerOffset = 0;
- pendingRequests = {};
- constructor(public dcId) {
- this.authorization = new Authorization(this);
- this.updateSession();
- }
- connect() {
- var { init, cipher, decipher } = generateObfuscatedInitPayload();
- this.cipher = cipher;
- this.decipher = decipher;
- this.socketConnection = new WebSocket(`wss://${sslSubdomains[this.dcId - 1]}-1.web.telegram.org:443/apiws`, ['binary']);
- this.socketConnection.binaryType = 'arraybuffer';
- this.socketConnection.onopen = () => {
- this.socketConnection.send(init);
- if (!this.authorization.authData.authKeyID) {
- this.authorization.start();
- return;
- } else {
- this.isConnecting = false;
- console.log('dawn we authorized from start');
- this.respondPending();
- }
- };
- // this.socketConnection.
- this.socketConnection.onmessage = (data) => {
- this.handleAnswer(data)
- };
- }
- respondPending() {
- let keys = Object.keys(this.pendingRequests)
- if (keys.length != 0) {
- console.log('start responding for');
- keys.forEach((it) => {
- let request = this.pendingRequests[it];
- console.log(request);
- this.sendApiMessage(request.method, request.payload, request.subject, request.generatedId)
- })
- }
- }
- sendPlainMessage(methodName, payload) {
- var generatedId = this.generateMessageID();
- let tlSerializator = new TLSerialization({ mtproto: true });
- tlSerializator.storeLong('0');
- tlSerializator.storeLong(generatedId);
- tlSerializator.storeInt(20);
- tlSerializator.storeMethod(methodName, payload);
- let tlLength = tlSerializator.offset;
- tlSerializator.offset = 16;
- tlSerializator.storeInt(tlLength - 20);
- tlSerializator.offset = tlLength
- let encrypted = this.cipher.encrypt(toIntermidiateEnvelope(tlSerializator.getBytes())).buffer;
- this.socketConnection.send(encrypted);
- }
- sendApiMessage(method, payload, answerSubject?, generatedId?) {
- if (!answerSubject) {
- answerSubject = new Subject();
- }
- if (!generatedId) {
- generatedId = this.generateMessageID();
- this.pendingRequests[generatedId] = {
- subject: answerSubject,
- method: method,
- payload: payload,
- generatedId,
- };
- }
- console.log('begin');
- console.log(method);
- if (!this.socketConnection) {
- console.log('begin connect to dc');
- this.connect();
- return answerSubject;
- }
- if (this.isConnecting) {
- console.log('still connecting');
- return answerSubject;
- }
- const tlMessage = new TLSerialization({ mtproto: false });
- console.log('plus seqno');
- if (!this.initConnection) {
- tlMessage.storeInt(0xda9b0d0d, 'invokeWithLayer')
- tlMessage.storeInt(105, 'layer')
- tlMessage.storeInt(0xc7481da6, 'initConnection')
- tlMessage.storeInt(1179180, 'api_id')
- tlMessage.storeString(navigator.userAgent || 'Unknown UserAgent', 'device_model')
- tlMessage.storeString(navigator.platform || 'Unknown Platform', 'system_version')
- tlMessage.storeString('1.0.1', 'app_version')
- tlMessage.storeString(navigator.language || 'en', 'system_lang_code')
- tlMessage.storeString('', 'lang_pack')
- tlMessage.storeString(navigator.language || 'en', 'lang_code')
- this.initConnection = true;
- }
- tlMessage.storeMethod(method, payload);
- this.sendEncryptedMessage(tlMessage, generatedId);
- return answerSubject;
- }
- sendEncryptedMessage(tlMessage: TLSerialization, generatedId, notContentRelated = false) {
- let authorization = this.authorization;
- let sessionID = this.sessionID;
- const tlSerializator = new TLSerialization({ mtproto: false });
- tlSerializator.storeLong(authorization.authData.serverSalt);
- tlSerializator.storeRawBytes(sessionID);
- tlSerializator.storeLong(generatedId);
- tlSerializator.storeInt(this.generateSeqNo(notContentRelated));
- tlSerializator.storeInt(tlMessage.offset);
- tlSerializator.storeRawBytes(tlMessage.getBytes());
- var paddingLength = (16 - (tlSerializator.offset % 16)) + 16 * (1 + nextRandomInt(5))
- var padding = randomBytes(paddingLength);
- var dataWithPadding = concat(tlSerializator.getBytes(), padding)
- const bytes = dataWithPadding;
- const msgKey = getMsgKey(dataWithPadding, true, authorization.authData.authKey);
- const keyIv = getMsgKeyIv(msgKey, true, this.authorization.authData.authKey)
- const encryptedBytes = aesEncryptSync(bytes, keyIv[0], keyIv[1])
- const request = new TLSerialization({ mtproto: false });
- request.storeRawBytes(this.authorization.authData.authKeyID);
- request.storeRawBytes(msgKey);
- request.storeRawBytes(encryptedBytes);
- let encrypted = this.cipher.encrypt(toIntermidiateEnvelope(request.getBytes())).buffer;
- this.socketConnection.send(encrypted);
- }
- updateSession() {
- this.seqNo = 0;
- this.prevSessionID = this.sessionID;
- this.sessionID = randomBytes(8);
- }
- handleAnswer(data) {
- const decryptedData = fromIntermidiateEnvelope(this.decipher.decrypt((new Uint8Array(data.data))));
- const authorization = this.authorization
- if (!authorization.isAuthorized) {
- authorization.onMessage(decryptedData)
- }
- if (authorization.isAuthorized && this.isConnecting) {
- this.isConnecting = false;
- this.respondPending();
- return;
- }
- if (authorization.isAuthorized) {
- let deser = new Desearelizator(decryptedData, false);
- let deserializerRaw = deser.desearelization;
- let length = deserializerRaw.fetchInt();
- const authKeyID = deserializerRaw.fetchIntBytes(64, 'auth_key_id');
- const msgKey = deserializerRaw.fetchIntBytes(128, 'msg_key');
- const encryptedData = deserializerRaw.fetchRawBytes(decryptedData.byteLength - deserializerRaw.getOffset(), 'encrypted_data')
- const keyIv = getMsgKeyIv(msgKey, false, authorization.authData.authKey)
- const dataWithPadding = new Uint8Array(aesDecryptSync(encryptedData, keyIv[0], keyIv[1]))
- const deserializer = new Desearelizator(dataWithPadding, false);
- deserializer.desearelization.fetchIntBytes(64, 'salt')
- const locSessionId = new Uint8Array(deserializer.desearelization.fetchIntBytes(64, 'session_id'))
- const messageId = deserializer.desearelization.fetchLong('messageid');
- const isInvalidSession =
- !bytesCmp(locSessionId, this.sessionID) && (
- !this.prevSessionID || !bytesCmp(locSessionId, this.prevSessionID));
- if (isInvalidSession) {
- console.warn(this.dcId + 'Sessions', this.sessionID, locSessionId, this.prevSessionID)
- // throw new Error(`[MT] Invalid server session_id: ${ bytesToHex(sessionID) }`)
- }
- const seqNoAnsw = deserializer.desearelization.fetchInt('seq_no');
- const messageBodyLength = deserializer.desearelization.fetchInt('message_data[length]')
- const messageBody = deserializer.desearelization.fetchRawBytes(messageBodyLength, 'message_data');
- // console.log('body');
- // console.log(messageBody);
- const bodyDeser = new TLDeserialization(messageBody.buffer, { mtproto: true });
- console.log('obob ' + this.dcId);
- let obobo = bodyDeser.fetchObject('Objdect');
- // if(obobo._ )
- // this.seqNo += 1;
- // if(obobo[''])
- this.handleResult(obobo, messageId);
- }
- }
- handleResult(resultObject, messageId) {
- console.log(resultObject);
- if (resultObject._ === 'bad_server_salt') {
- this.authorization.updateSalt(resultObject.new_server_salt);
- this.respondPending();
- return;
- }
- if (resultObject['_'] === 'rpc_result') {
- console.log('plus seqno answer');
- console.log('add on rpc result');
- this.acknowledge(messageId);
- if (resultObject.result && resultObject.result.error_code && resultObject.result.error_message == 'AUTH_KEY_UNREGISTERED') {
- currentDc.sendApiMessage('auth.exportAuthorization', {
- dc_id: this.dcId,
- }).subscribe((it) => {
- console.log('got dat key');
- console.log(it);
- this.sendApiMessage('auth.importAuthorization', it);
- });
- return;
- }
- if (resultObject.result && resultObject.result.error_code && resultObject.result.error_message.indexOf('MIGRATE') !== -1) {
- currentDc = dataCenters[(+resultObject.result.error_message.slice(-1)) - 1];
- currentDc.pendingRequests = this.pendingRequests;
- this.pendingRequests = {};
- currentDc.respondPending();
- return;
- }
- if (resultObject.result._ == 'auth.authorization') {
- console.log('authorized dat bitch');
- console.log(this.pendingRequests);
- if (this.pendingRequests[resultObject['req_msg_id']])
- this.pendingRequests[resultObject['req_msg_id']].subject.next(resultObject['result']);
- delete this.pendingRequests[resultObject['req_msg_id']];
- this.updateSession();
- this.respondPending();
- }
- if (this.pendingRequests[resultObject['req_msg_id']])
- this.pendingRequests[resultObject['req_msg_id']].subject.next(resultObject['result']);
- delete this.pendingRequests[resultObject['req_msg_id']];
- }
- if (resultObject['_'] === 'msg_container') {
- resultObject.messages.forEach((it) => {
- this.handleResult(it.body, it.msg_id);
- })
- }
- }
- generateMessageID() {
- const timeTicks = tsNow(),
- timeSec = Math.floor(timeTicks / 1000) + this.timerOffset,
- timeMSec = timeTicks % 1000,
- random = nextRandomInt(0xFFFF)
- let messageID = [timeSec, timeMSec << 21 | random << 3 | 4]
- if (this.lastMessageID[0] > messageID[0] ||
- this.lastMessageID[0] == messageID[0] && this.lastMessageID[1] >= messageID[1]) {
- messageID = [this.lastMessageID[0], this.lastMessageID[1] + 4]
- }
- this.lastMessageID = messageID
- // console.log('generated msg id', messageID, timerOffset)
- return lshift32(messageID[0], messageID[1])
- };
- applyServerTime(serverTime, localTime) {
- console.log('apply server time');
- console.log(serverTime);
- const newTimeOffset = serverTime - Math.floor((localTime || tsNow()) / 1000)
- const changed = Math.abs(this.timerOffset - newTimeOffset) > 10
- this.timerOffset = newTimeOffset
- this.lastMessageID = [0, 0]
- if (changed) {
- console.log('changed offset');
- }
- return changed
- };
- generateSeqNo(notContentRelated) {
- var seqNo = this.seqNo * 2
- //
- if (!notContentRelated) {
- seqNo++;
- this.seqNo++
- }
- return seqNo
- }
- acknowledge(msgid) {
- let ser = new TLSerialization({});
- ser.storeObject({
- _: 'msgs_ack',
- msg_ids: [msgid],
- }, 'MsgsAck');
- this.sendEncryptedMessage(ser, this.generateMessageID(), true)
- }
- }
- var sslSubdomains = ['pluto', 'venus', 'aurora', 'vesta', 'flora'];
- var dataCenters = [
- new DataCenter(1),
- new DataCenter(2),
- new DataCenter(3),
- new DataCenter(4),
- new DataCenter(5),
- ];
- let dcNumber = (JSON.parse(localStorage.getItem('auth') || `{}`).dcId-1) || 1;
- let currentDc = dataCenters[dcNumber];
- // currentDc.connect();
- function getMsgKeyIv(msgKey: number[], isOut: boolean, authKey: Uint8Array) {
- authKey = new Uint8Array(authKey);
- const x = isOut
- ? 0
- : 8;
- var sha2aText = new Uint8Array(52);
- var sha2bText = new Uint8Array(52);
- sha2aText.set(msgKey, 0)
- sha2aText.set(authKey.subarray(x, x + 36), 16)
- sha2aText = sha256HashSync(sha2aText);
- sha2bText.set(authKey.subarray(40 + x, 40 + x + 36), 0)
- sha2bText.set(msgKey, 36)
- sha2bText = sha256HashSync(sha2bText)
- var aesKey = new Uint8Array(32)
- var aesIv = new Uint8Array(32)
- var sha2a = new Uint8Array(sha2aText)
- var sha2b = new Uint8Array(sha2bText)
- aesKey.set(sha2a.subarray(0, 8))
- aesKey.set(sha2b.subarray(8, 24), 8)
- aesKey.set(sha2a.subarray(24, 32), 24)
- aesIv.set(sha2b.subarray(0, 8))
- aesIv.set(sha2a.subarray(8, 24), 8)
- aesIv.set(sha2b.subarray(24, 32), 24)
- return [aesKey, aesIv]
- }
- function getMsgKey(dataWithPadding, isOut, authKey: Uint8Array) {
- authKey = new Uint8Array(authKey)
- var x = isOut ? 0 : 8
- var msgKeyLargePlain = concat(authKey.subarray(88 + x, 88 + x + 32), dataWithPadding);
- let withSha = sha256HashSync(msgKeyLargePlain);
- var msgKey = new Uint8Array(withSha).subarray(8, 24)
- return msgKey;
- }
- function toIntermidiateEnvelope(payload: Uint8Array) {
- let length = new Uint8Array(intToByteArray(payload.length));
- return concat(length, payload);
- }
- function fromIntermidiateEnvelope(payload: Uint8Array) {
- return payload.slice(payload.slice(4, numberFromByteArray(payload.slice(0, 4))))
- }
- // generateObfuscatedInitPayload();
- function generateObfuscatedInitPayload() {
- let result = generateRandomKey();
- let reversed = new Uint8Array(result).reverse();
- let encryptKey = substr(result, 8, 32);
- let encryptIv = substr(result, 40, 16);
- let decryptKey = substr(reversed, 8, 32);
- let decryptIv = substr(reversed, 40, 16);
- let cipher = new aesjs.ModeOfOperation.ctr(encryptKey, encryptIv);
- let decipher = new aesjs.ModeOfOperation.ctr(decryptKey, decryptIv);
- let encrypted = new Uint8Array(cipher.encrypt(result));
- return { init: concat(substr(result, 0, 56), substr(encrypted, 56, 8)), cipher, decipher };
- }
- function generateRandomKey() {
- let funcResult;
- while (!funcResult) {
- let start = randomBytes(56);
- let protocol = new Uint8Array([238, 238, 238, 238]);
- let dcId = new Uint8Array([2, 0]);
- let random = randomBytes(2);
- let result = concat(start, protocol, dcId, random);
- if (result[0] == 0xef) {
- continue;
- }
- let deprecated = [
- 0x44414548,
- 0x54534f50,
- 0x20544547,
- 0x4954504f,
- 0xdddddddd,
- 0xeeeeeeee,
- ];
- if (deprecated.indexOf(numberFromByteArray(substr(result, 0, 4))) != -1) {
- continue;
- }
- funcResult = result
- }
- return funcResult;
- }
- function tsNow(seconds) {
- var t = +new Date() + (0)
- return seconds ? Math.floor(t / 1000) : t
- }
- window.tsNow = tsNow;
- function nextRandomInt(maxValue) {
- return Math.floor(Math.random() * maxValue)
- }
- window.tgApi = {
- sendCode: (phoneNumber) => {
- return currentDc.sendApiMessage('auth.sendCode', {
- phone_number: phoneNumber,
- api_id: -123,
- api_hash: '-',
- settings: {
- _: 'codeSettings',
- allow_flashcall: false,
- current_number: false,
- allow_app_hash: true,
- },
- });
- },
- signIn: (phoneNumber, phoneCodeHash, phoneCode) => {
- console.log('nop nop nop2')
- return currentDc.sendApiMessage('auth.signIn', {
- phone_number: phoneNumber,
- phone_code_hash: phoneCodeHash,
- phone_code: phoneCode,
- });
- },
- signUp: (phoneNumber, phoneCodeHash, name, lastname) => {
- return currentDc.sendApiMessage('auth.signUp', {
- phone_number: phoneNumber,
- phone_code_hash: phoneCodeHash,
- first_name: name,
- last_name: lastname
- });
- },
- getDialogs: () => {
- console.log('get that sweet dialogs');
- return currentDc.sendApiMessage('messages.getDialogs', {
- exclude_pinned: false,
- folder_id: 0,
- offset_date: 0,
- offset_id: 0,
- offset_peer: { _: 'inputPeerEmpty' },
- limit: 20,
- hash: 0,
- });
- },
- getMoreDialogs: (offset_date, offset_id, offset_peer) => {
- console.log('get that sweet dialogs');
- return currentDc.sendApiMessage('messages.getDialogs', {
- exclude_pinned: true,
- folder_id: 0,
- offset_date,
- offset_id,
- offset_peer,
- limit: 20,
- hash: 0,
- });
- },
- getPeerPhoto(peerPhoto) {
- console.log(peerPhoto);
- return dataCenters[peerPhoto.dc_id - 1].sendApiMessage('upload.getFile', {
- location: {
- _: 'inputPeerPhotoFileLocation',
- peer: peerPhoto.inputPeer,
- volume_id: peerPhoto.volume_id,
- local_id: peerPhoto.local_id,
- },
- offset: 0,
- limit: 1024 * 1024,
- });
- },
- getPhoto(dcId, photoId, accessHash, fileReference, type) {
- return dataCenters[dcId - 1].sendApiMessage('upload.getFile', {
- location: {
- _: 'inputPhotoFileLocation',
- id: photoId,
- access_hash: accessHash,
- file_reference: fileReference,
- thumb_size: type,
- },
- offset: 0,
- limit: 1024 * 1024,
- });
- },
- getMessages: (offset_date, offset_id, peer) => {
- console.log('get that sweet dialogs');
- return currentDc.sendApiMessage('messages.getHistory', {
- offset_date,
- offset_id,
- peer,
- add_offset: 0,
- limit: 20,
- hash: 0,
- max_id: 0,
- min_id: 0,
- });
- },
- getPassword: () => {
- console.log('get that sweet dialogs');
- return currentDc.sendApiMessage('account.getPassword', {});
- },
- getDataCenter: ()=>{
- return currentDc;
- },
- checkPassword: (srpId, A, m1) => {
- console.log('get that sweet dialogs');
- return currentDc.sendApiMessage('auth.checkPassword', {
- password: {
- _: 'inputCheckPasswordSRP',
- srp_id: srpId,
- A: A,
- M1: m1,
- },
- });
- },
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement