Advertisement
Dubovitksiydev

Untitled

Feb 17th, 2020
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.87 KB | None | 0 0
  1. // import {pqPrimeLeemon} from './crypto';
  2. import { Authorization } from './mtproto';
  3. import { Subject } from 'rxjs';
  4.  
  5. let json;
  6. let api;
  7. let mtproto;
  8.  
  9. fetch('/mtproto.json').then((it) => {
  10. it.json().then((answa) => {
  11. json = {
  12. constructors: toMap(answa.constructors, 'predicate'),
  13. constructorIds: toMap(answa.constructors, 'id'),
  14. constructorTypes: toMap(answa.constructors, 'type'),
  15. methods: toMap(answa.methods, 'method'),
  16. };
  17. window.mtproto = json;
  18. mtproto = window.mtproto;
  19. if (!currentDc.authorization.authData.authKeyID) {
  20. window.json = window.mtproto;
  21. }
  22. // sendPlainMessage('req_pq', { nonce: randomBytes(nonce) });
  23. });
  24. });
  25. fetch('/api.json').then((it) => {
  26. it.json().then((answa) => {
  27. window.api = {
  28. constructors: toMap(answa.constructors, 'predicate'),
  29. constructorIds: toMap(answa.constructors, 'id'),
  30. constructorTypes: toMap(answa.constructors, 'type'),
  31. methods: toMap(answa.methods, 'method'),
  32. };
  33. api = window.api;
  34. if (currentDc.authorization.authData.authKeyID) {
  35. window.json = window.api;
  36. }
  37. // sendPlainMessage('req_pq', { nonce: randomBytes(nonce) });
  38. });
  39. });
  40.  
  41. export class DataCenter {
  42. seqNo = 0;
  43.  
  44. authorization;
  45. socketConnection: WebSocket;
  46.  
  47. isConnecting = true;
  48. initConnection = false;
  49. sendCode = false;
  50.  
  51. sessionID;
  52. prevSessionID;
  53.  
  54. cipher;
  55. decipher;
  56.  
  57. lastMessageID = [0, 0];
  58. timerOffset = 0;
  59.  
  60. pendingRequests = {};
  61.  
  62. constructor(public dcId) {
  63. this.authorization = new Authorization(this);
  64. this.updateSession();
  65. }
  66.  
  67. connect() {
  68. var { init, cipher, decipher } = generateObfuscatedInitPayload();
  69. this.cipher = cipher;
  70. this.decipher = decipher;
  71. this.socketConnection = new WebSocket(`wss://${sslSubdomains[this.dcId - 1]}-1.web.telegram.org:443/apiws`, ['binary']);
  72. this.socketConnection.binaryType = 'arraybuffer';
  73.  
  74. this.socketConnection.onopen = () => {
  75. this.socketConnection.send(init);
  76. if (!this.authorization.authData.authKeyID) {
  77. this.authorization.start();
  78. return;
  79. } else {
  80. this.isConnecting = false;
  81. console.log('dawn we authorized from start');
  82. this.respondPending();
  83. }
  84. };
  85. // this.socketConnection.
  86. this.socketConnection.onmessage = (data) => {
  87. this.handleAnswer(data)
  88. };
  89.  
  90. }
  91.  
  92. respondPending() {
  93. let keys = Object.keys(this.pendingRequests)
  94. if (keys.length != 0) {
  95. console.log('start responding for');
  96. keys.forEach((it) => {
  97. let request = this.pendingRequests[it];
  98. console.log(request);
  99. this.sendApiMessage(request.method, request.payload, request.subject, request.generatedId)
  100. })
  101. }
  102. }
  103.  
  104. sendPlainMessage(methodName, payload) {
  105. var generatedId = this.generateMessageID();
  106. let tlSerializator = new TLSerialization({ mtproto: true });
  107. tlSerializator.storeLong('0');
  108. tlSerializator.storeLong(generatedId);
  109. tlSerializator.storeInt(20);
  110. tlSerializator.storeMethod(methodName, payload);
  111. let tlLength = tlSerializator.offset;
  112. tlSerializator.offset = 16;
  113. tlSerializator.storeInt(tlLength - 20);
  114. tlSerializator.offset = tlLength
  115. let encrypted = this.cipher.encrypt(toIntermidiateEnvelope(tlSerializator.getBytes())).buffer;
  116. this.socketConnection.send(encrypted);
  117. }
  118.  
  119.  
  120. sendApiMessage(method, payload, answerSubject?, generatedId?) {
  121.  
  122. if (!answerSubject) {
  123. answerSubject = new Subject();
  124. }
  125.  
  126. if (!generatedId) {
  127. generatedId = this.generateMessageID();
  128. this.pendingRequests[generatedId] = {
  129. subject: answerSubject,
  130. method: method,
  131. payload: payload,
  132. generatedId,
  133. };
  134. }
  135. console.log('begin');
  136. console.log(method);
  137. if (!this.socketConnection) {
  138. console.log('begin connect to dc');
  139. this.connect();
  140. return answerSubject;
  141. }
  142. if (this.isConnecting) {
  143. console.log('still connecting');
  144. return answerSubject;
  145. }
  146. const tlMessage = new TLSerialization({ mtproto: false });
  147. console.log('plus seqno');
  148. if (!this.initConnection) {
  149. tlMessage.storeInt(0xda9b0d0d, 'invokeWithLayer')
  150. tlMessage.storeInt(105, 'layer')
  151. tlMessage.storeInt(0xc7481da6, 'initConnection')
  152. tlMessage.storeInt(1179180, 'api_id')
  153. tlMessage.storeString(navigator.userAgent || 'Unknown UserAgent', 'device_model')
  154. tlMessage.storeString(navigator.platform || 'Unknown Platform', 'system_version')
  155. tlMessage.storeString('1.0.1', 'app_version')
  156. tlMessage.storeString(navigator.language || 'en', 'system_lang_code')
  157. tlMessage.storeString('', 'lang_pack')
  158. tlMessage.storeString(navigator.language || 'en', 'lang_code')
  159. this.initConnection = true;
  160. }
  161. tlMessage.storeMethod(method, payload);
  162. this.sendEncryptedMessage(tlMessage, generatedId);
  163. return answerSubject;
  164. }
  165.  
  166. sendEncryptedMessage(tlMessage: TLSerialization, generatedId, notContentRelated = false) {
  167. let authorization = this.authorization;
  168. let sessionID = this.sessionID;
  169. const tlSerializator = new TLSerialization({ mtproto: false });
  170. tlSerializator.storeLong(authorization.authData.serverSalt);
  171. tlSerializator.storeRawBytes(sessionID);
  172. tlSerializator.storeLong(generatedId);
  173. tlSerializator.storeInt(this.generateSeqNo(notContentRelated));
  174.  
  175. tlSerializator.storeInt(tlMessage.offset);
  176. tlSerializator.storeRawBytes(tlMessage.getBytes());
  177.  
  178. var paddingLength = (16 - (tlSerializator.offset % 16)) + 16 * (1 + nextRandomInt(5))
  179. var padding = randomBytes(paddingLength);
  180. var dataWithPadding = concat(tlSerializator.getBytes(), padding)
  181.  
  182. const bytes = dataWithPadding;
  183. const msgKey = getMsgKey(dataWithPadding, true, authorization.authData.authKey);
  184. const keyIv = getMsgKeyIv(msgKey, true, this.authorization.authData.authKey)
  185. const encryptedBytes = aesEncryptSync(bytes, keyIv[0], keyIv[1])
  186. const request = new TLSerialization({ mtproto: false });
  187. request.storeRawBytes(this.authorization.authData.authKeyID);
  188. request.storeRawBytes(msgKey);
  189. request.storeRawBytes(encryptedBytes);
  190.  
  191. let encrypted = this.cipher.encrypt(toIntermidiateEnvelope(request.getBytes())).buffer;
  192. this.socketConnection.send(encrypted);
  193. }
  194.  
  195. updateSession() {
  196. this.seqNo = 0;
  197. this.prevSessionID = this.sessionID;
  198. this.sessionID = randomBytes(8);
  199. }
  200.  
  201. handleAnswer(data) {
  202. const decryptedData = fromIntermidiateEnvelope(this.decipher.decrypt((new Uint8Array(data.data))));
  203. const authorization = this.authorization
  204. if (!authorization.isAuthorized) {
  205. authorization.onMessage(decryptedData)
  206. }
  207. if (authorization.isAuthorized && this.isConnecting) {
  208. this.isConnecting = false;
  209. this.respondPending();
  210. return;
  211. }
  212. if (authorization.isAuthorized) {
  213. let deser = new Desearelizator(decryptedData, false);
  214. let deserializerRaw = deser.desearelization;
  215. let length = deserializerRaw.fetchInt();
  216. const authKeyID = deserializerRaw.fetchIntBytes(64, 'auth_key_id');
  217. const msgKey = deserializerRaw.fetchIntBytes(128, 'msg_key');
  218. const encryptedData = deserializerRaw.fetchRawBytes(decryptedData.byteLength - deserializerRaw.getOffset(), 'encrypted_data')
  219.  
  220.  
  221. const keyIv = getMsgKeyIv(msgKey, false, authorization.authData.authKey)
  222. const dataWithPadding = new Uint8Array(aesDecryptSync(encryptedData, keyIv[0], keyIv[1]))
  223. const deserializer = new Desearelizator(dataWithPadding, false);
  224. deserializer.desearelization.fetchIntBytes(64, 'salt')
  225. const locSessionId = new Uint8Array(deserializer.desearelization.fetchIntBytes(64, 'session_id'))
  226. const messageId = deserializer.desearelization.fetchLong('messageid');
  227. const isInvalidSession =
  228. !bytesCmp(locSessionId, this.sessionID) && (
  229. !this.prevSessionID || !bytesCmp(locSessionId, this.prevSessionID));
  230. if (isInvalidSession) {
  231. console.warn(this.dcId + 'Sessions', this.sessionID, locSessionId, this.prevSessionID)
  232. // throw new Error(`[MT] Invalid server session_id: ${ bytesToHex(sessionID) }`)
  233. }
  234. const seqNoAnsw = deserializer.desearelization.fetchInt('seq_no');
  235. const messageBodyLength = deserializer.desearelization.fetchInt('message_data[length]')
  236. const messageBody = deserializer.desearelization.fetchRawBytes(messageBodyLength, 'message_data');
  237. // console.log('body');
  238. // console.log(messageBody);
  239. const bodyDeser = new TLDeserialization(messageBody.buffer, { mtproto: true });
  240. console.log('obob ' + this.dcId);
  241. let obobo = bodyDeser.fetchObject('Objdect');
  242.  
  243. // if(obobo._ )
  244. // this.seqNo += 1;
  245. // if(obobo[''])
  246. this.handleResult(obobo, messageId);
  247. }
  248. }
  249.  
  250. handleResult(resultObject, messageId) {
  251. console.log(resultObject);
  252. if (resultObject._ === 'bad_server_salt') {
  253. this.authorization.updateSalt(resultObject.new_server_salt);
  254. this.respondPending();
  255. return;
  256. }
  257.  
  258. if (resultObject['_'] === 'rpc_result') {
  259. console.log('plus seqno answer');
  260. console.log('add on rpc result');
  261. this.acknowledge(messageId);
  262. if (resultObject.result && resultObject.result.error_code && resultObject.result.error_message == 'AUTH_KEY_UNREGISTERED') {
  263. currentDc.sendApiMessage('auth.exportAuthorization', {
  264. dc_id: this.dcId,
  265. }).subscribe((it) => {
  266. console.log('got dat key');
  267. console.log(it);
  268. this.sendApiMessage('auth.importAuthorization', it);
  269. });
  270. return;
  271. }
  272.  
  273. if (resultObject.result && resultObject.result.error_code && resultObject.result.error_message.indexOf('MIGRATE') !== -1) {
  274. currentDc = dataCenters[(+resultObject.result.error_message.slice(-1)) - 1];
  275. currentDc.pendingRequests = this.pendingRequests;
  276. this.pendingRequests = {};
  277. currentDc.respondPending();
  278. return;
  279. }
  280.  
  281. if (resultObject.result._ == 'auth.authorization') {
  282. console.log('authorized dat bitch');
  283. console.log(this.pendingRequests);
  284. if (this.pendingRequests[resultObject['req_msg_id']])
  285. this.pendingRequests[resultObject['req_msg_id']].subject.next(resultObject['result']);
  286. delete this.pendingRequests[resultObject['req_msg_id']];
  287. this.updateSession();
  288. this.respondPending();
  289. }
  290. if (this.pendingRequests[resultObject['req_msg_id']])
  291. this.pendingRequests[resultObject['req_msg_id']].subject.next(resultObject['result']);
  292. delete this.pendingRequests[resultObject['req_msg_id']];
  293. }
  294.  
  295. if (resultObject['_'] === 'msg_container') {
  296. resultObject.messages.forEach((it) => {
  297. this.handleResult(it.body, it.msg_id);
  298. })
  299. }
  300. }
  301.  
  302. generateMessageID() {
  303. const timeTicks = tsNow(),
  304. timeSec = Math.floor(timeTicks / 1000) + this.timerOffset,
  305. timeMSec = timeTicks % 1000,
  306. random = nextRandomInt(0xFFFF)
  307.  
  308. let messageID = [timeSec, timeMSec << 21 | random << 3 | 4]
  309. if (this.lastMessageID[0] > messageID[0] ||
  310. this.lastMessageID[0] == messageID[0] && this.lastMessageID[1] >= messageID[1]) {
  311. messageID = [this.lastMessageID[0], this.lastMessageID[1] + 4]
  312. }
  313.  
  314. this.lastMessageID = messageID
  315.  
  316. // console.log('generated msg id', messageID, timerOffset)
  317.  
  318. return lshift32(messageID[0], messageID[1])
  319. };
  320.  
  321. applyServerTime(serverTime, localTime) {
  322. console.log('apply server time');
  323. console.log(serverTime);
  324. const newTimeOffset = serverTime - Math.floor((localTime || tsNow()) / 1000)
  325. const changed = Math.abs(this.timerOffset - newTimeOffset) > 10
  326. this.timerOffset = newTimeOffset
  327.  
  328. this.lastMessageID = [0, 0]
  329. if (changed) {
  330. console.log('changed offset');
  331. }
  332. return changed
  333. };
  334.  
  335. generateSeqNo(notContentRelated) {
  336. var seqNo = this.seqNo * 2
  337. //
  338. if (!notContentRelated) {
  339. seqNo++;
  340. this.seqNo++
  341. }
  342. return seqNo
  343. }
  344.  
  345. acknowledge(msgid) {
  346. let ser = new TLSerialization({});
  347. ser.storeObject({
  348. _: 'msgs_ack',
  349. msg_ids: [msgid],
  350. }, 'MsgsAck');
  351. this.sendEncryptedMessage(ser, this.generateMessageID(), true)
  352. }
  353. }
  354.  
  355. var sslSubdomains = ['pluto', 'venus', 'aurora', 'vesta', 'flora'];
  356. var dataCenters = [
  357. new DataCenter(1),
  358. new DataCenter(2),
  359. new DataCenter(3),
  360. new DataCenter(4),
  361. new DataCenter(5),
  362. ];
  363.  
  364. let dcNumber = (JSON.parse(localStorage.getItem('auth') || `{}`).dcId-1) || 1;
  365.  
  366. let currentDc = dataCenters[dcNumber];
  367.  
  368. // currentDc.connect();
  369. function getMsgKeyIv(msgKey: number[], isOut: boolean, authKey: Uint8Array) {
  370. authKey = new Uint8Array(authKey);
  371. const x = isOut
  372. ? 0
  373. : 8;
  374. var sha2aText = new Uint8Array(52);
  375. var sha2bText = new Uint8Array(52);
  376.  
  377. sha2aText.set(msgKey, 0)
  378. sha2aText.set(authKey.subarray(x, x + 36), 16)
  379. sha2aText = sha256HashSync(sha2aText);
  380.  
  381. sha2bText.set(authKey.subarray(40 + x, 40 + x + 36), 0)
  382. sha2bText.set(msgKey, 36)
  383. sha2bText = sha256HashSync(sha2bText)
  384.  
  385. var aesKey = new Uint8Array(32)
  386. var aesIv = new Uint8Array(32)
  387. var sha2a = new Uint8Array(sha2aText)
  388. var sha2b = new Uint8Array(sha2bText)
  389.  
  390. aesKey.set(sha2a.subarray(0, 8))
  391. aesKey.set(sha2b.subarray(8, 24), 8)
  392. aesKey.set(sha2a.subarray(24, 32), 24)
  393.  
  394. aesIv.set(sha2b.subarray(0, 8))
  395. aesIv.set(sha2a.subarray(8, 24), 8)
  396. aesIv.set(sha2b.subarray(24, 32), 24)
  397.  
  398. return [aesKey, aesIv]
  399. }
  400.  
  401. function getMsgKey(dataWithPadding, isOut, authKey: Uint8Array) {
  402. authKey = new Uint8Array(authKey)
  403. var x = isOut ? 0 : 8
  404. var msgKeyLargePlain = concat(authKey.subarray(88 + x, 88 + x + 32), dataWithPadding);
  405. let withSha = sha256HashSync(msgKeyLargePlain);
  406. var msgKey = new Uint8Array(withSha).subarray(8, 24)
  407. return msgKey;
  408. }
  409.  
  410.  
  411. function toIntermidiateEnvelope(payload: Uint8Array) {
  412. let length = new Uint8Array(intToByteArray(payload.length));
  413. return concat(length, payload);
  414. }
  415.  
  416. function fromIntermidiateEnvelope(payload: Uint8Array) {
  417. return payload.slice(payload.slice(4, numberFromByteArray(payload.slice(0, 4))))
  418. }
  419.  
  420.  
  421. // generateObfuscatedInitPayload();
  422.  
  423. function generateObfuscatedInitPayload() {
  424. let result = generateRandomKey();
  425. let reversed = new Uint8Array(result).reverse();
  426. let encryptKey = substr(result, 8, 32);
  427. let encryptIv = substr(result, 40, 16);
  428. let decryptKey = substr(reversed, 8, 32);
  429. let decryptIv = substr(reversed, 40, 16);
  430. let cipher = new aesjs.ModeOfOperation.ctr(encryptKey, encryptIv);
  431. let decipher = new aesjs.ModeOfOperation.ctr(decryptKey, decryptIv);
  432. let encrypted = new Uint8Array(cipher.encrypt(result));
  433. return { init: concat(substr(result, 0, 56), substr(encrypted, 56, 8)), cipher, decipher };
  434. }
  435.  
  436. function generateRandomKey() {
  437. let funcResult;
  438. while (!funcResult) {
  439. let start = randomBytes(56);
  440. let protocol = new Uint8Array([238, 238, 238, 238]);
  441.  
  442. let dcId = new Uint8Array([2, 0]);
  443. let random = randomBytes(2);
  444. let result = concat(start, protocol, dcId, random);
  445. if (result[0] == 0xef) {
  446. continue;
  447. }
  448. let deprecated = [
  449. 0x44414548,
  450. 0x54534f50,
  451. 0x20544547,
  452. 0x4954504f,
  453. 0xdddddddd,
  454. 0xeeeeeeee,
  455. ];
  456.  
  457. if (deprecated.indexOf(numberFromByteArray(substr(result, 0, 4))) != -1) {
  458. continue;
  459. }
  460. funcResult = result
  461. }
  462. return funcResult;
  463. }
  464.  
  465.  
  466. function tsNow(seconds) {
  467. var t = +new Date() + (0)
  468. return seconds ? Math.floor(t / 1000) : t
  469. }
  470.  
  471. window.tsNow = tsNow;
  472.  
  473. function nextRandomInt(maxValue) {
  474. return Math.floor(Math.random() * maxValue)
  475. }
  476.  
  477.  
  478. window.tgApi = {
  479. sendCode: (phoneNumber) => {
  480. return currentDc.sendApiMessage('auth.sendCode', {
  481. phone_number: phoneNumber,
  482. api_id: -123,
  483. api_hash: '-',
  484. settings: {
  485. _: 'codeSettings',
  486. allow_flashcall: false,
  487. current_number: false,
  488. allow_app_hash: true,
  489. },
  490. });
  491. },
  492. signIn: (phoneNumber, phoneCodeHash, phoneCode) => {
  493. console.log('nop nop nop2')
  494. return currentDc.sendApiMessage('auth.signIn', {
  495. phone_number: phoneNumber,
  496. phone_code_hash: phoneCodeHash,
  497. phone_code: phoneCode,
  498. });
  499. },
  500.  
  501. signUp: (phoneNumber, phoneCodeHash, name, lastname) => {
  502. return currentDc.sendApiMessage('auth.signUp', {
  503. phone_number: phoneNumber,
  504. phone_code_hash: phoneCodeHash,
  505. first_name: name,
  506. last_name: lastname
  507. });
  508. },
  509. getDialogs: () => {
  510. console.log('get that sweet dialogs');
  511. return currentDc.sendApiMessage('messages.getDialogs', {
  512. exclude_pinned: false,
  513. folder_id: 0,
  514. offset_date: 0,
  515. offset_id: 0,
  516. offset_peer: { _: 'inputPeerEmpty' },
  517. limit: 20,
  518. hash: 0,
  519. });
  520. },
  521.  
  522. getMoreDialogs: (offset_date, offset_id, offset_peer) => {
  523. console.log('get that sweet dialogs');
  524. return currentDc.sendApiMessage('messages.getDialogs', {
  525. exclude_pinned: true,
  526. folder_id: 0,
  527. offset_date,
  528. offset_id,
  529. offset_peer,
  530. limit: 20,
  531. hash: 0,
  532. });
  533. },
  534. getPeerPhoto(peerPhoto) {
  535. console.log(peerPhoto);
  536. return dataCenters[peerPhoto.dc_id - 1].sendApiMessage('upload.getFile', {
  537. location: {
  538. _: 'inputPeerPhotoFileLocation',
  539. peer: peerPhoto.inputPeer,
  540. volume_id: peerPhoto.volume_id,
  541. local_id: peerPhoto.local_id,
  542. },
  543. offset: 0,
  544. limit: 1024 * 1024,
  545. });
  546. },
  547.  
  548. getPhoto(dcId, photoId, accessHash, fileReference, type) {
  549. return dataCenters[dcId - 1].sendApiMessage('upload.getFile', {
  550. location: {
  551. _: 'inputPhotoFileLocation',
  552. id: photoId,
  553. access_hash: accessHash,
  554. file_reference: fileReference,
  555. thumb_size: type,
  556. },
  557. offset: 0,
  558. limit: 1024 * 1024,
  559. });
  560. },
  561.  
  562. getMessages: (offset_date, offset_id, peer) => {
  563. console.log('get that sweet dialogs');
  564. return currentDc.sendApiMessage('messages.getHistory', {
  565. offset_date,
  566. offset_id,
  567. peer,
  568. add_offset: 0,
  569. limit: 20,
  570. hash: 0,
  571. max_id: 0,
  572. min_id: 0,
  573. });
  574. },
  575.  
  576. getPassword: () => {
  577. console.log('get that sweet dialogs');
  578. return currentDc.sendApiMessage('account.getPassword', {});
  579. },
  580.  
  581. getDataCenter: ()=>{
  582. return currentDc;
  583. },
  584. checkPassword: (srpId, A, m1) => {
  585. console.log('get that sweet dialogs');
  586. return currentDc.sendApiMessage('auth.checkPassword', {
  587. password: {
  588. _: 'inputCheckPasswordSRP',
  589. srp_id: srpId,
  590. A: A,
  591. M1: m1,
  592. },
  593. });
  594. },
  595. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement