Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@mtproto/core

Package Overview
Dependencies
Maintainers
1
Versions
43
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@mtproto/core - npm Package Compare versions

Comparing version 3.1.1 to 3.2.0

src/storage/temp/index.cjs

32

package.json
{
"name": "@mtproto/core",
"version": "3.1.1",
"version": "3.2.0",
"description": "Telegram API (MTProto) client library for browser and nodejs",

@@ -32,2 +32,5 @@ "keywords": [

],
"engines": {
"node": ">=12"
},
"types": "./index.d.ts",

@@ -91,2 +94,13 @@ "browser": {

},
"./src/storage/local/package.json": "./src/storage/local/package.json",
"./src/storage/local": {
"require": "./src/storage/local/index.cjs",
"import": "./src/storage/local/index.js",
"browser": "./src/storage/local/index.browser.js"
},
"./src/storage/temp/package.json": "./src/storage/temp/package.json",
"./src/storage/temp": {
"require": "./src/storage/temp/index.cjs",
"import": "./src/storage/temp/index.js"
},
"./src/tl/deserializer/package.json": "./src/tl/deserializer/package.json",

@@ -102,8 +116,2 @@ "./src/tl/deserializer": {

},
"./src/storage/local/package.json": "./src/storage/local/package.json",
"./src/storage/local": {
"require": "./src/storage/local/index.cjs",
"import": "./src/storage/local/index.js",
"browser": "./src/storage/local/index.browser.js"
},
"./src/transport/obfuscated/package.json": "./src/transport/obfuscated/package.json",

@@ -119,7 +127,2 @@ "./src/transport/obfuscated": {

},
"./src/transport/tcp/package.json": "./src/transport/tcp/package.json",
"./src/transport/tcp": {
"require": "./src/transport/tcp/index.cjs",
"import": "./src/transport/tcp/index.js"
},
"./src/utils/common/package.json": "./src/utils/common/package.json",

@@ -140,2 +143,7 @@ "./src/utils/common": {

},
"./src/transport/tcp/package.json": "./src/transport/tcp/package.json",
"./src/transport/tcp": {
"require": "./src/transport/tcp/index.cjs",
"import": "./src/transport/tcp/index.js"
},
"./src/utils/rsa/package.json": "./src/utils/rsa/package.json",

@@ -142,0 +150,0 @@ "./src/utils/rsa": {

@@ -9,3 +9,3 @@ # @mtproto/core

* **Actual.** 112 layer in the API scheme
* **Actual.** 113 layer in the API scheme
* **Fast.** Uses WebSocket for browser and TCP for nodejs

@@ -38,5 +38,2 @@ * **Easy.** Cryptography and bytes is hidden. [Just make requests](#mtprotocallmethod-params-options--promise) to the API

api_hash,
// Use test servers
test: true,
});

@@ -52,6 +49,31 @@

### `new MTProto({ api_id, api_hash, test }) => mtproto`
### `new MTProto({ api_id, api_hash, test, customLocalStorage }) => mtproto`
Example in [quick start](#quick-start).
#### `api_id: number` and `api_hash: string`
**api_id** and **api_hash** are required. If you do not have them yet, then get them according to the official instructions: [creating your Telegram application](https://core.telegram.org/api/obtaining_api_id).
#### `test: boolean`
Default: `false`. Use test data centers. On test servers, you can use [test phone numbers](https://core.telegram.org/api/auth#test-phone-numbers).
#### `customLocalStorage: localStorage`
Default for browser: `window.localStorage`. Default for nodejs: [`node-localstorage`](https://github.com/alik0211/mtproto-core/blob/master/src/storage/local/index.js). Custom storage for save auth data. Your localStorage must follow this API:
```ts
interface MyLocalStorage {
setItem(key: string, value: string): void;
getItem(key: string): string;
}
```
We have ready-made storage:
1. [tempLocalStorage](https://github.com/alik0211/mtproto-core/blob/master/src/storage/temp/index.js) only stores data while the script is running
Example:
```js
const { tempLocalStorage } = require('@mtproto/core/src/storage/temp');
const mtproto = new MTProto({
customLocalStorage: tempLocalStorage,
});
```
### `mtproto.call(method, params, options) => Promise`

@@ -63,13 +85,10 @@

#### `params: object`
Parameters for `method` from `https://core.telegram.org/method/{method}#parameters`.
If you need to pass a constructor use `_`. Example for [auth.sendCode](https://core.telegram.org/method/auth.sendCode#parameters):
If you need to pass a constructor use `_`. Example for [users.getFullUser](https://core.telegram.org/method/users.getFullUser#parameters):
```js
const params = {
// api_id and api_hash @mtproto/core will set automatically
phone_number: '+9996621111',
settings: {
_: 'codeSettings',
}
id: {
_: 'inputUserSelf',
},
};

@@ -82,3 +101,3 @@ ```

#### `options.syncAuth: boolean`
By default, it is `true`. Tells the @mtproto/core to copy authorization to all DC if the response contains `auth.authorization`.
Default: `true`. Copy authorization to all DC if the response contains `auth.authorization`.

@@ -85,0 +104,0 @@ #### Example:

@@ -55,3 +55,5 @@ import EventEmitter from 'events';

class MTProto {
constructor({ api_id, api_hash, test = false }) {
constructor(options) {
const { api_id, api_hash, test = false, customLocalStorage } = options;
this.api_id = api_id;

@@ -62,2 +64,4 @@ this.api_hash = api_hash;

this.customLocalStorage = customLocalStorage;
this.updates = new EventEmitter();

@@ -67,3 +71,3 @@

this.storage = new Storage();
this.storage = new Storage('', { customLocalStorage });

@@ -141,3 +145,3 @@ this.setDefaultDc();

const { api_id, api_hash, updates } = this;
const { api_id, api_hash, updates, customLocalStorage } = this;

@@ -149,2 +153,3 @@ this.rpcs[dcId] = new RPC({

updates,
storage: new Storage(dc.id, { customLocalStorage }),
});

@@ -151,0 +156,0 @@ }

import bigInt from 'big-integer';
import debounce from 'lodash.debounce';
import { meta } from '../meta/index.js';
import { Storage } from '../storage/index.js';
import { Transport } from '../transport/index.js';

@@ -15,6 +14,6 @@ import TLSerializer from '../tl/serializer/index.js';

bigIntToBytes,
longToBytes,
longFromInts,
longToBytesRaw,
intsToLong,
getRandomInt,
convertToByteArray,
bytesToBytesRaw,
xorBytes,

@@ -27,3 +26,3 @@ } from '../utils/common/index.js';

class RPC {
constructor({ api_id, api_hash, dc, updates }) {
constructor({ api_id, api_hash, dc, updates, storage }) {
this.api_id = api_id;

@@ -39,13 +38,12 @@ this.api_hash = api_hash;

this.storage = new Storage(this.dc.id);
this.storage.set('timeOffset', 0);
this.storage = storage;
this.updateSession();
this.handleTransportError = this.handleTransportError.bind(this);
this.handleTransportOpen = this.handleTransportOpen.bind(this);
this.handleTransportClose = this.handleTransportClose.bind(this);
this.handleTransportMessage = this.handleTransportMessage.bind(this);
this.transport = new Transport(this.dc);
this.connect();
this.transport.on('open', this.handleTransportOpen.bind(this));
this.transport.on('close', this.handleTransportClose.bind(this));
this.transport.on('error', this.handleTransportError.bind(this));
this.transport.on('message', this.handleTransportMessage.bind(this));

@@ -73,2 +71,3 @@ this.sendAcks = debounce(() => {

}
async handleTransportError(payload) {

@@ -85,4 +84,2 @@ const { type } = payload;

this.storage.pSet('serverSalt', null);
return this.recconect();
}

@@ -96,2 +93,3 @@

}
async handleTransportOpen(event) {

@@ -120,5 +118,7 @@ const authKey = this.storage.pGet('authKey');

}
async handleTransportClose(event) {
this.recconect();
this.isReady = false;
}
async handleTransportMessage(buffer) {

@@ -130,3 +130,2 @@ this.handleMessage(buffer);

const deserializer = new TLDeserializer(buffer);
const auth_key_id = deserializer.long('auth_key_id');

@@ -144,2 +143,6 @@ const msg_id = deserializer.long('msg_id');

if (!bytesIsEqual(this.nonce, nonce)) {
throw new Error('The nonce are not equal');
}
const publicKey = await getRsaKeyByFingerprints(

@@ -196,3 +199,12 @@ server_public_key_fingerprints

const serverDH = deserializer.predicate('Server_DH_Params');
const { nonce, server_nonce, encrypted_answer } = serverDH;
if (!bytesIsEqual(this.nonce, nonce)) {
throw new Error('The nonce are not equal');
}
if (!bytesIsEqual(this.serverNonce, server_nonce)) {
throw new Error('The server_nonce are not equal');
}
this.tmpAesKey = concatBytes(

@@ -209,3 +221,3 @@ await SHA1(concatBytes(this.newNonce, this.serverNonce)),

const decryptedData = new AES.IGE(this.tmpAesKey, this.tmpAesIV).decrypt(
serverDH.encrypted_answer
encrypted_answer
);

@@ -216,3 +228,2 @@ const innerDataHash = decryptedData.slice(0, 20);

);
const serverDHInnerData = innerDeserializer.predicate(

@@ -222,2 +233,11 @@ 'Server_DH_inner_data'

if (
!bytesIsEqual(
innerDataHash,
await SHA1(decryptedData.slice(20, 20 + innerDeserializer.offset))
)
) {
throw new Error('Invalid hash in DH params decrypted data');
}
this.storage.set(

@@ -249,7 +269,7 @@ 'timeOffset',

if (gA.compareTo(bigInt.one) <= 0) {
if (gA.lesserOrEquals(bigInt.one)) {
throw new Error('Server_DH_inner_data.g_a incorrect: g_a <= 1');
}
if (gA.compareTo(dhPrime.subtract(bigInt.one)) >= 0) {
if (gA.greaterOrEquals(dhPrime.minus(bigInt.one))) {
throw new Error(

@@ -262,9 +282,9 @@ 'Server_DH_inner_data.g_a incorrect: g_a >= dh_prime - 1'

if (gA.compareTo(twoPow) < 0) {
if (gA.lesser(twoPow)) {
throw new Error('Server_DH_inner_data.g_a incorrect: g_a < 2^{2048-64}');
}
if (gA.compareTo(dhPrime.subtract(twoPow)) >= 0) {
if (gA.greaterOrEquals(dhPrime.minus(twoPow))) {
throw new Error(
'Server_DH_inner_data.g_a incorrect: g_a > dh_prime - 2^{2048-64}'
'Server_DH_inner_data.g_a incorrect: g_a >= dh_prime - 2^{2048-64}'
);

@@ -276,12 +296,13 @@ }

const b = bytesToBigInt(getRandomBytes(256));
const authKey = convertToByteArray(
bigIntToBytes(this.gA.modPow(b, this.dhPrime))
const authKey = bigIntToBytes(this.gA.modPow(b, this.dhPrime));
const serverSalt = xorBytes(
this.newNonce.slice(0, 8),
this.serverNonce.slice(0, 8)
);
const serverSalt = convertToByteArray(
xorBytes(this.newNonce.slice(0, 8), this.serverNonce.slice(0, 8))
);
this.storage.pSet('authKey', authKey);
this.storage.pSet('serverSalt', serverSalt);
this.storage.pSet('authKey', bytesToBytesRaw(authKey));
this.storage.pSet('serverSalt', bytesToBytesRaw(serverSalt));
this.authKeyAuxHash = bytesToBytesRaw((await SHA1(authKey)).slice(0, 8));
const innerSerializer = new TLSerializer();

@@ -325,10 +346,55 @@ innerSerializer.predicate(

);
const { nonce, server_nonce } = serverDHAnswer;
if (!bytesIsEqual(this.nonce, nonce)) {
throw new Error('The nonce are not equal');
}
if (!bytesIsEqual(this.serverNonce, server_nonce)) {
throw new Error('The server_nonce are not equal');
}
if (serverDHAnswer._ === 'dh_gen_ok') {
const hash = (
await SHA1(concatBytes(this.newNonce, [1], this.authKeyAuxHash))
).slice(4, 20);
if (!bytesIsEqual(hash, serverDHAnswer.new_nonce_hash1)) {
throw new Error(`Invalid hash in dh_gen_ok`);
}
this.handleMessage = this.handleEncryptedMessage;
this.isReady = true;
this.sendWaitMessages();
} else {
console.error(`Invalid Set_client_DH_params_answer:`, serverDHAnswer);
return;
}
if (serverDHAnswer._ === 'dh_gen_retry') {
const hash = (
await SHA1(concatBytes(this.newNonce, [2], this.authKeyAuxHash))
).slice(4, 20);
if (!bytesIsEqual(hash, serverDHAnswer.new_nonce_hash2)) {
throw new Error(`Invalid hash in dh_gen_retry`);
}
this.generateDH(this.authKeyAuxHash);
return;
}
if (serverDHAnswer._ === 'dh_gen_fail') {
const hash = (
await SHA1(concatBytes(this.newNonce, [3], this.authKeyAuxHash))
).slice(4, 20);
if (!bytesIsEqual(hash, serverDHAnswer.new_nonce_hash3)) {
throw new Error(`Invalid hash in dh_gen_fail`);
}
throw new Error(`dh_gen_fail`);
}
throw new Error(`Invalid Set_client_DH_params_answer: ${serverDHAnswer}`);
}

@@ -358,4 +424,38 @@

const plainDeserializer = new TLDeserializer(plaintextData.buffer);
const computedMessageKey = (
await SHA256(concatBytes(authKey.slice(96, 128), plaintextData))
).slice(8, 24);
if (!bytesIsEqual(messageKey, computedMessageKey)) {
console.warn(`Incorrect msg_key`);
return;
}
const self = this;
const plainDeserializer = new TLDeserializer(plaintextData.buffer, {
predicatesHandlers: {
rpc_result(result) {
result.req_msg_id = this.long();
const waitMessage = self.messagesWaitResponse.get(result.req_msg_id);
if (!waitMessage) {
console.warn(
`RPC result for a non-existent message with id ${result.req_msg_id}`
);
}
const constructorId = this.uint32();
this.offset -= 4;
const type =
constructorId === 558156313 ? 'rpc_error' : waitMessage.type;
result.result = this.predicate(type);
},
},
});
const salt = plainDeserializer.long();

@@ -367,2 +467,19 @@ const sessionId = plainDeserializer.long();

if (length > plaintextData.length) {
console.warn(
`Length in message ${messageId} to exceed the plaintext length:`,
`${length} > ${plaintextData.length}`
);
return;
}
if (length % 4 !== 0) {
console.warn(
`Length ${length} in message ${messageId} is not a multiple of four`
);
return;
}
const result = plainDeserializer.predicate();

@@ -380,23 +497,38 @@

const { messageId } = params;
let waitMessage = null;
switch (message._) {
case 'msg_container':
message.messages.forEach(message => {
this.handleDecryptedMessage(message.body, {
messageId: message.msg_id,
});
if (bigInt(messageId).isEven()) {
console.warn(`Message id from server is even:`, message);
return;
}
if (message._ === 'msg_container') {
message.messages.forEach(message => {
this.handleDecryptedMessage(message.body, {
messageId: message.msg_id,
});
return;
});
case 'bad_server_salt':
waitMessage = this.messagesWaitResponse.get(message.bad_msg_id);
return;
}
if (!waitMessage) {
throw new Error(
`bad_server_salt. Not found message with id ${message.bad_msg_id}`
);
}
if (['bad_server_salt', 'bad_msg_notification'].includes(message._)) {
if (message.error_code === 48) {
this.storage.pSet(
'serverSalt',
longToBytesRaw(message.new_server_salt)
);
}
this.storage.pSet('serverSalt', longToBytes(message.new_server_salt));
if ([16, 17].includes(message.error_code)) {
const serverTime = bigInt(messageId).shiftRight(32).toJSNumber();
const timeOffset = Math.floor(Date.now() / 1000) - serverTime;
this.storage.set('timeOffset', timeOffset);
this.lastMessageId = [0, 0];
}
const waitMessage = this.messagesWaitResponse.get(message.bad_msg_id);
if (waitMessage) {
this.call(waitMessage.method, waitMessage.params)

@@ -406,47 +538,38 @@ .then(waitMessage.resolve)

this.messagesWaitResponse.delete(message.bad_msg_id);
this.ackMessage(messageId);
return;
} else {
console.warn(`${message._} for a non-existent message:`, message);
}
case 'bad_msg_notification':
return;
return;
}
case 'new_session_created':
this.ackMessage(messageId);
if (message._ === 'new_session_created') {
this.ackMessage(messageId);
this.storage.pSet('serverSalt', longToBytesRaw(message.server_salt));
// this.messagesWaitResponse.delete(message.first_msg_id);
this.storage.pSet('serverSalt', longToBytes(message.server_salt));
return;
}
return;
if (message._ === 'msgs_ack') {
return;
}
case 'msgs_ack':
// console.log(`msgs_ack:`, message.msg_ids);
// console.log(`this.messagesWaitResponse:`, this.messagesWaitResponse);
// message.msg_ids.forEach(msgId => {
// this.pendingAcks.forEach((pendingAckMsgId, index) => {
// if (msgId === pendingAckMsgId) {
// this.pendingAcks.splice(index, 1);
// }
// });
// });
return;
if (message._ === 'rpc_result') {
this.ackMessage(messageId);
case 'rpc_result':
this.ackMessage(messageId);
const waitMessage = this.messagesWaitResponse.get(message.req_msg_id);
waitMessage = this.messagesWaitResponse.get(message.req_msg_id);
if (message.result._ === 'rpc_error') {
waitMessage.reject(message.result);
} else {
waitMessage.resolve(message.result);
}
if (message.result._ === 'rpc_error') {
waitMessage.reject(message.result);
} else {
waitMessage.resolve(message.result);
}
this.messagesWaitResponse.delete(message.req_msg_id);
this.messagesWaitResponse.delete(message.req_msg_id);
return;
return;
}
default:
this.ackMessage(messageId);
this.updates.emit(message._, message);
return;
}
this.ackMessage(messageId);
this.updates.emit(message._, message);
}

@@ -470,3 +593,3 @@

serializer.method('invokeWithLayer', {
layer: 112,
layer: 113,
});

@@ -484,5 +607,5 @@

serializer.method(method, {
api_hash: this.api_hash, // TODO: not found in scheme
api_id: this.api_id, // TODO: not found in scheme
const type = serializer.method(method, {
api_hash: this.api_hash,
api_id: this.api_id,
...params,

@@ -493,3 +616,3 @@ });

const messageId = await this.sendEncryptedMessage(serializer.getBytes());
const messageIdAsKey = longFromInts(messageId[0], messageId[1]);
const messageIdAsKey = intsToLong(messageId[0], messageId[1]);

@@ -499,2 +622,3 @@ this.messagesWaitResponse.set(messageIdAsKey, {

params,
type,
resolve,

@@ -624,3 +748,6 @@ reject,

this.sessionId = getRandomBytes(8);
this.lastMessageId = [0, 0];
this.lastMessageId = [
0, // low
0, // high
];
}

@@ -648,21 +775,4 @@

}
connect() {
this.transport = new Transport(this.dc);
this.transport.on('error', this.handleTransportError);
this.transport.on('open', this.handleTransportOpen);
this.transport.on('close', this.handleTransportClose);
this.transport.on('message', this.handleTransportMessage);
}
recconect() {
this.isReady = false;
this.transport.destroy();
this.connect();
}
}
export { RPC };

@@ -6,4 +6,8 @@ import { localStorage } from './local/index.js';

class Storage {
constructor(prefix) {
constructor(prefix, options = {}) {
this._prefix = prefix;
const { customLocalStorage = localStorage } = options;
this.localStorage = customLocalStorage;
}

@@ -34,3 +38,3 @@

localStorage.setItem(key, JSON.stringify(value));
this.localStorage.setItem(key, JSON.stringify(value));
}

@@ -43,4 +47,4 @@

if (localStorage.getItem(key)) {
cache[key] = JSON.parse(localStorage.getItem(key));
if (this.localStorage.getItem(key)) {
cache[key] = JSON.parse(this.localStorage.getItem(key));

@@ -47,0 +51,0 @@ return cache[key];

@@ -8,6 +8,4 @@ import envPaths from 'env-paths';

console.log(`Auth data is located in ${paths.data}`);
const localStorage = new LocalStorage(paths.data);
export { localStorage };
import pako from 'pako';
import bigInt from 'big-integer';
import { schema } from '../../../scheme/index.js';
import { uintToInt } from '../../utils/common/index.js';
import { intsToLong } from '../../utils/common/index.js';
class TLDeserializer {
constructor(buffer) {
constructor(buffer, options = {}) {
const { predicatesHandlers = {} } = options;
this.buffer = buffer;

@@ -17,2 +18,4 @@ this.byteView = new Uint8Array(this.buffer);

this.offset = 0;
this.predicatesHandlers = predicatesHandlers;
}

@@ -33,6 +36,6 @@

long() {
const iLow = this.uint32();
const iHigh = this.uint32();
const high = this.uint32();
const low = this.uint32();
const result = bigInt(iHigh).shiftLeft(32).add(bigInt(iLow)).toString();
const result = intsToLong(low, high);

@@ -123,13 +126,16 @@ return result;

if (type.substr(0, 6).toLowerCase() === 'vector') {
if (type.charAt(0) === 'V') {
let constructor = this.int();
let constructorCmp = uintToInt(constructor);
const isContainer = type.charAt(0) === '%';
if (constructorCmp != 0x1cb5c415) {
throw new Error('Invalid vector constructor ' + constructorCmp);
}
}
const constructorId = isContainer ? 1538843921 : this.uint32();
const length = this.int();
if (constructorId === 812830625) {
const gzipBytes = this.bytes();
const uncompressed = pako.inflate(gzipBytes);
const deserializer = new TLDeserializer(uncompressed.buffer);
return deserializer.predicate(type);
}
if (type.substr(0, 6).toLowerCase() === 'vector') {
const length = type.charAt(0) === 'V' ? this.int() : constructorId;
const result = [];

@@ -149,14 +155,2 @@

const isContainer = type.charAt(0) === '%';
const constructorId = isContainer ? 1538843921 : this.uint32();
if (constructorId === 812830625) {
const gzipBytes = this.bytes();
const uncompressed = pako.inflate(gzipBytes);
const deserializer = new TLDeserializer(uncompressed.buffer);
return deserializer.predicate(type);
}
const constructor = schema.constructorsById[constructorId];

@@ -172,28 +166,32 @@

constructor.params.forEach(param => {
let paramType = param.type;
if (result._ in this.predicatesHandlers) {
this.predicatesHandlers[result._].call(this, result);
} else {
constructor.params.forEach(param => {
let paramType = param.type;
if (paramType === '#' && result.pFlags === undefined) {
result.pFlags = {};
}
if (paramType === '#' && result.pFlags === undefined) {
result.pFlags = {};
}
const isFlag = paramType.indexOf('?') !== -1;
const isFlag = paramType.indexOf('?') !== -1;
if (isFlag) {
const condType = paramType.split('?');
const fieldBit = condType[0].split('.');
if (!(result[fieldBit[0]] & (1 << fieldBit[1]))) {
return;
if (isFlag) {
const condType = paramType.split('?');
const fieldBit = condType[0].split('.');
if (!(result[fieldBit[0]] & (1 << fieldBit[1]))) {
return;
}
paramType = condType[1];
}
paramType = condType[1];
}
const value = this.predicate(paramType);
const value = this.predicate(paramType);
if (isFlag && paramType === 'true') {
result.pFlags[param.name] = value;
} else {
result[param.name] = value;
}
});
if (isFlag && paramType === 'true') {
result.pFlags[param.name] = value;
} else {
result[param.name] = value;
}
});
}

@@ -200,0 +198,0 @@ return result;

@@ -83,2 +83,4 @@ import bigInt from 'big-integer';

});
return methodData.type;
}

@@ -219,7 +221,11 @@

if (value.length === 2) {
this.uint32(value[1]);
this.uint32(value[0]);
const [low, high] = value;
return;
this.uint32(high);
this.uint32(low);
} else {
this.bytesRaw(value);
}
return;
}

@@ -229,4 +235,4 @@

this.int(intToUint(remainder.toJSNumber()));
this.int(intToUint(quotient.toJSNumber()));
this.uint32(remainder.toJSNumber());
this.uint32(quotient.toJSNumber());
}

@@ -233,0 +239,0 @@

import { Obfuscated } from '../obfuscated/index.js';
const subdomainsMap = {
1: 'pluto',
2: 'venus',
3: 'aurora',
4: 'vesta',
5: 'flora',
};
class Socket extends Obfuscated {

@@ -8,17 +16,17 @@ constructor(dc) {

this.dc = dc;
this.url = `wss://${subdomainsMap[this.dc.id]}.web.telegram.org${
this.dc.test ? '/apiws_test' : '/apiws'
}`;
this.setUrl();
this.connect();
}
connect() {
this.socket = new WebSocket(this.url, 'binary');
this.socket.binaryType = 'arraybuffer';
this.handleError = this.handleError.bind(this);
this.handleOpen = this.handleOpen.bind(this);
this.handleClose = this.handleClose.bind(this);
this.handleMessage = this.handleMessage.bind(this);
this.socket.addEventListener('error', this.handleError);
this.socket.addEventListener('open', this.handleOpen);
this.socket.addEventListener('close', this.handleClose);
this.socket.addEventListener('message', this.handleMessage);
this.socket.addEventListener('error', this.handleError.bind(this));
this.socket.addEventListener('open', this.handleOpen.bind(this));
this.socket.addEventListener('close', this.handleClose.bind(this));
this.socket.addEventListener('message', this.handleMessage.bind(this));
}

@@ -40,3 +48,9 @@

async handleClose(event) {
if (this.socket.readyState === 1) {
this.socket.close();
}
this.emit('close', event);
this.connect();
}

@@ -56,31 +70,8 @@

const buffer = (await this.obfuscate(intermediateBytes)).buffer;
const { buffer } = await this.obfuscate(intermediateBytes);
this.socket.send(buffer);
}
destroy() {
this.removeAllListeners();
if (this.socket.readyState === 1) {
this.socket.close();
}
}
setUrl() {
const subdomainsMap = {
1: 'pluto',
2: 'venus',
3: 'aurora',
4: 'vesta',
5: 'flora',
};
const dcId = this.dc.id;
const urlPath = this.dc.test ? '/apiws_test' : '/apiws';
this.url = `wss://${subdomainsMap[dcId]}.web.telegram.org${urlPath}`;
}
}
export { Socket };

@@ -10,9 +10,2 @@ import { Socket } from 'net';

this.handleConnect = this.handleConnect.bind(this);
this.handleData = this.handleData.bind(this);
this.handleError = this.handleError.bind(this);
this.handleClose = this.handleClose.bind(this);
this.stream = new Uint8Array();
this.connect();

@@ -22,9 +15,15 @@ }

connect() {
this.stream = new Uint8Array();
this.socket = new Socket();
this.socket.on('data', this.handleData);
this.socket.on('error', this.handleError);
this.socket.on('close', this.handleClose);
this.socket.on('data', this.handleData.bind(this));
this.socket.on('error', this.handleError.bind(this));
this.socket.on('close', this.handleClose.bind(this));
this.socket.connect(this.dc.port, this.dc.ip, this.handleConnect);
this.socket.connect(
this.dc.port,
this.dc.ip,
this.handleConnect.bind(this)
);
}

@@ -39,7 +38,4 @@

while (true) {
if (this.stream.length < 8) {
break;
}
// The minimum length is eight (transport error with a intermediate header)
while (this.stream.length >= 8) {
const dataView = new DataView(this.stream.buffer);

@@ -75,4 +71,10 @@ const payloadLength = dataView.getUint32(0, true);

async handleClose() {
async handleClose(hadError) {
if (!this.socket.destroyed) {
this.socket.destroy();
}
this.emit('close');
this.connect();
}

@@ -94,14 +96,4 @@

}
destroy() {
this.removeAllListeners();
// TODO: Remove this.socket.on
if (!this.socket.destroyed) {
this.socket.destroy();
}
}
}
export { TCP };

@@ -22,34 +22,29 @@ import bigInt from 'big-integer';

function hexToBytes(str, len) {
if (!len) {
len = Math.ceil(str.length / 2);
function hexToBytesRaw(value, length) {
if (!length) {
length = Math.ceil(value.length / 2);
}
while (str.length < len * 2) {
str = '0' + str;
while (value.length < length * 2) {
value = '0' + value;
}
const buf = new Uint8Array(len);
for (let i = 0; i < len; i++) {
buf[i] = parseInt(str.slice(i * 2, i * 2 + 2), 16);
const bytes = [];
for (let i = 0; i < length; i++) {
bytes.push(parseInt(value.slice(i * 2, i * 2 + 2), 16));
}
return buf;
return bytes;
}
function hexToBytes(value, length) {
return new Uint8Array(hexToBytesRaw(value, length));
}
function bytesToBigInt(bytes) {
const digits = new Array(bytes.byteLength);
for (let i = 0; i < bytes.byteLength; i++) {
digits[i] =
bytes[i] < 16 ? '0' + bytes[i].toString(16) : bytes[i].toString(16);
}
return bigInt(digits.join(''), 16);
return bigInt(bytesToHex(bytes), 16);
}
// function getRandomBytes(length) {
// const bytes = new Uint8Array(length);
// crypto.getRandomValues(bytes);
// return bytes;
// }
function xorBytes(bytes1, bytes2) {
let bytes = new Uint8Array(bytes1.byteLength);
for (let i = 0; i < bytes1.byteLength; i++) {
let bytes = new Uint8Array(bytes1.length);
for (let i = 0; i < bytes1.length; i++) {
bytes[i] = bytes1[i] ^ bytes2[i];

@@ -86,114 +81,22 @@ }

function bytesFromHex(hexString) {
var len = hexString.length,
i;
var start = 0;
var bytes = [];
function bytesToBytesRaw(bytes) {
const result = [];
if (hexString.length % 2) {
bytes.push(parseInt(hexString.charAt(0), 16));
start++;
for (let i = 0; i < bytes.length; i++) {
result.push(bytes[i]);
}
for (i = start; i < len; i += 2) {
bytes.push(parseInt(hexString.substr(i, 2), 16));
}
return bytes;
return result;
}
function bytesXor(bytes1, bytes2) {
var len = bytes1.length;
var bytes = [];
function longToBytesRaw(value) {
const result = hexToBytesRaw(bigInt(value).toString(16), 8).reverse();
for (var i = 0; i < len; ++i) {
bytes[i] = bytes1[i] ^ bytes2[i];
}
return bytes;
return result;
}
function bytesFromWords(wordArray) {
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
var bytes = [];
for (var i = 0; i < sigBytes; i++) {
bytes.push((words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff);
}
return bytes;
function intsToLong(low, high) {
return bigInt(low).shiftLeft(32).add(bigInt(high)).toString(10);
}
function bytesFromBigInt(bigInt, len) {
var bytes = bigInt.toByteArray();
if (len && bytes.length < len) {
var padding = [];
for (var i = 0, needPadding = len - bytes.length; i < needPadding; i++) {
padding[i] = 0;
}
if (bytes instanceof ArrayBuffer) {
bytes = bufferConcat(padding, bytes);
} else {
bytes = padding.concat(bytes);
}
} else {
while (!bytes[0] && (!len || bytes.length > len)) {
bytes = bytes.slice(1);
}
}
return bytes;
}
function convertToUint8Array(bytes) {
if (bytes.buffer !== undefined) {
return bytes;
}
return new Uint8Array(bytes);
}
function convertToByteArray(bytes) {
if (Array.isArray(bytes)) {
return bytes;
}
bytes = convertToUint8Array(bytes);
var newBytes = [];
for (var i = 0, len = bytes.length; i < len; i++) {
newBytes.push(bytes[i]);
}
return newBytes;
}
function bufferConcat(buffer1, buffer2) {
var l1 = buffer1.byteLength || buffer1.length;
var l2 = buffer2.byteLength || buffer2.length;
var tmp = new Uint8Array(l1 + l2);
tmp.set(
buffer1 instanceof ArrayBuffer ? new Uint8Array(buffer1) : buffer1,
0
);
tmp.set(
buffer2 instanceof ArrayBuffer ? new Uint8Array(buffer2) : buffer2,
l1
);
return tmp.buffer;
}
function longToInts(sLong) {
const { quotient, remainder } = bigInt(sLong).divmod(bigInt(0x100000000));
return [uintToInt(quotient.toJSNumber()), uintToInt(remainder.toJSNumber())];
}
function longToBytes(sLong) {
return bytesFromWords({ words: longToInts(sLong), sigBytes: 8 }).reverse();
}
function longFromInts(high, low) {
return bigInt(high).shiftLeft(32).add(bigInt(low)).toString(10);
}
function intToUint(value) {

@@ -219,2 +122,3 @@ value = +value;

bigIntToBytes,
hexToBytesRaw,
hexToBytes,

@@ -226,12 +130,5 @@ bytesToBigInt,

bytesToHex,
bytesFromHex,
bytesXor,
bytesFromWords,
bytesFromBigInt,
convertToUint8Array,
convertToByteArray,
bufferConcat,
longToInts,
longToBytes,
longFromInts,
bytesToBytesRaw,
longToBytesRaw,
intsToLong,
intToUint,

@@ -238,0 +135,0 @@ uintToInt,

@@ -17,7 +17,7 @@ import {

} from 'leemon';
import { bytesFromHex, bytesToBigInt, getRandomInt } from '../common/index.js';
import { hexToBytes, bytesToBigInt, getRandomInt } from '../common/index.js';
function bytesFromLeemonBigInt(bigInt, len) {
var str = bigInt2str(bigInt, 16);
return bytesFromHex(str);
return hexToBytes(str);
}

@@ -24,0 +24,0 @@

import bigInt from 'big-integer';
import TLSerializer from '../../tl/serializer/index.js';
import { bytesToHex, bytesFromHex } from '../../utils/common/index.js';
import { bytesToHex, hexToBytes } from '../../utils/common/index.js';
import { SHA1 } from '../../utils/crypto/index.js';

@@ -39,4 +39,4 @@

const RSAPublicKey = new TLSerializer();
RSAPublicKey.bytes(bytesFromHex(publisKey.modulus), 'n');
RSAPublicKey.bytes(bytesFromHex(publisKey.exponent), 'e');
RSAPublicKey.bytes(hexToBytes(publisKey.modulus), 'n');
RSAPublicKey.bytes(hexToBytes(publisKey.exponent), 'e');

@@ -43,0 +43,0 @@ const buffer = RSAPublicKey.getBuffer();

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc