@mtcute/test 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/client.d.ts +8 -3
- package/cjs/client.js +20 -21
- package/cjs/client.js.map +1 -1
- package/cjs/client.test.d.ts +1 -0
- package/cjs/client.test.js +32 -0
- package/cjs/client.test.js.map +1 -0
- package/cjs/crypto.d.ts +6 -0
- package/cjs/crypto.js +162 -0
- package/cjs/crypto.js.map +1 -0
- package/cjs/index.d.ts +2 -0
- package/cjs/index.js +2 -0
- package/cjs/index.js.map +1 -1
- package/cjs/storage-test.d.ts +24 -0
- package/cjs/storage-test.js +302 -0
- package/cjs/storage-test.js.map +1 -0
- package/cjs/storage.test.d.ts +1 -0
- package/cjs/storage.test.js +43 -0
- package/cjs/storage.test.js.map +1 -0
- package/cjs/stub.test.d.ts +1 -0
- package/cjs/stub.test.js +55 -0
- package/cjs/stub.test.js.map +1 -0
- package/cjs/transport.test.d.ts +1 -0
- package/cjs/transport.test.js +35 -0
- package/cjs/transport.test.js.map +1 -0
- package/cjs/utils.test.d.ts +1 -0
- package/cjs/utils.test.js +16 -0
- package/cjs/utils.test.js.map +1 -0
- package/esm/client.d.ts +8 -3
- package/esm/client.js +21 -22
- package/esm/client.js.map +1 -1
- package/esm/client.test.d.ts +1 -0
- package/esm/client.test.js +30 -0
- package/esm/client.test.js.map +1 -0
- package/esm/crypto.d.ts +6 -0
- package/esm/crypto.js +154 -0
- package/esm/crypto.js.map +1 -0
- package/esm/index.d.ts +2 -0
- package/esm/index.js +2 -0
- package/esm/index.js.map +1 -1
- package/esm/storage-test.d.ts +24 -0
- package/esm/storage-test.js +294 -0
- package/esm/storage-test.js.map +1 -0
- package/esm/storage.test.d.ts +1 -0
- package/esm/storage.test.js +41 -0
- package/esm/storage.test.js.map +1 -0
- package/esm/stub.test.d.ts +1 -0
- package/esm/stub.test.js +50 -0
- package/esm/stub.test.js.map +1 -0
- package/esm/transport.test.d.ts +1 -0
- package/esm/transport.test.js +33 -0
- package/esm/transport.test.js.map +1 -0
- package/esm/utils.test.d.ts +1 -0
- package/esm/utils.test.js +14 -0
- package/esm/utils.test.js.map +1 -0
- package/package.json +4 -3
package/esm/client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BaseTelegramClient } from '@mtcute/core';
|
|
1
|
+
import { BaseTelegramClient, tl } from '@mtcute/core';
|
|
2
2
|
import { StubMemoryTelegramStorage } from './storage.js';
|
|
3
3
|
import { StubTelegramTransport } from './transport.js';
|
|
4
4
|
import { markedIdToPeer } from './utils.js';
|
|
@@ -45,25 +45,27 @@ export class StubTelegramClient extends BaseTelegramClient {
|
|
|
45
45
|
this._lastDate = Math.floor(Date.now() / 1000);
|
|
46
46
|
this._lastSeq = 0;
|
|
47
47
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
/**
|
|
49
|
+
* Create a fake client that may not actually be used for API calls
|
|
50
|
+
*
|
|
51
|
+
* Useful for testing "offline" methods
|
|
52
|
+
*/
|
|
53
|
+
static offline() {
|
|
54
|
+
const client = new StubTelegramClient();
|
|
55
|
+
client.call = (obj) => {
|
|
56
|
+
throw new Error(`Expected offline client to not make any API calls (method called: ${obj._})`);
|
|
57
|
+
};
|
|
58
|
+
return client;
|
|
56
59
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
this.
|
|
60
|
+
async registerPeers(...peers) {
|
|
61
|
+
for (const peer of peers) {
|
|
62
|
+
if (tl.isAnyUser(peer)) {
|
|
63
|
+
this._knownUsers.set(peer.id, peer);
|
|
61
64
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
this._selfId = user.id;
|
|
65
|
+
else {
|
|
66
|
+
this._knownChats.set(peer.id, peer);
|
|
67
|
+
}
|
|
68
|
+
await this._cachePeersFrom(peer);
|
|
67
69
|
}
|
|
68
70
|
}
|
|
69
71
|
getPeers(ids) {
|
|
@@ -118,12 +120,9 @@ export class StubTelegramClient extends BaseTelegramClient {
|
|
|
118
120
|
this.respondWith(method, responder);
|
|
119
121
|
}
|
|
120
122
|
respondWith(method, response) {
|
|
121
|
-
if (typeof response !== 'function') {
|
|
122
|
-
const res = response;
|
|
123
|
-
response = () => res;
|
|
124
|
-
}
|
|
125
123
|
// eslint-disable-next-line
|
|
126
124
|
this._responders.set(method, response);
|
|
125
|
+
return response;
|
|
127
126
|
}
|
|
128
127
|
async call(message, params) {
|
|
129
128
|
if (this._responders.has(message._)) {
|
package/esm/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseTelegramClient, BaseTelegramClientOptions, MaybeAsync, MustEqual, RpcCallOptions, tl } from '@mtcute/core'\n\nimport { StubMemoryTelegramStorage } from './storage.js'\nimport { StubTelegramTransport } from './transport.js'\nimport { InputResponder } from './types.js'\nimport { markedIdToPeer } from './utils.js'\n\ninterface MessageBox {\n pts: number\n lastMessageId: number\n}\n\ntype InputPeerId = number | tl.TypePeer | false | undefined\n\nexport class StubTelegramClient extends BaseTelegramClient {\n constructor(params?: Partial<BaseTelegramClientOptions>) {\n const storage = new StubMemoryTelegramStorage({\n hasKeys: true,\n hasTempKeys: true,\n })\n\n super({\n apiId: 0,\n apiHash: '',\n logLevel: 0,\n storage,\n transport: () => {\n const transport = new StubTelegramTransport({\n onMessage: (data) => {\n if (!this._onRawMessage) {\n if (this._responders.size) {\n this._emitError(new Error('Unexpected outgoing message'))\n }\n\n return\n }\n\n const dcId = transport._currentDc!.id\n const key = storage.getAuthKeyFor(dcId)\n\n if (key) {\n this._onRawMessage(storage.decryptOutgoingMessage(transport._crypto, data, dcId))\n }\n },\n })\n\n return transport\n },\n ...params,\n })\n }\n\n // some fake peers handling //\n\n readonly _knownChats = new Map<number, tl.TypeChat>()\n readonly _knownUsers = new Map<number, tl.TypeUser>()\n _selfId = 0\n\n registerChat(chat: tl.TypeChat | tl.TypeChat[]): void {\n if (Array.isArray(chat)) {\n for (const c of chat) {\n this.registerChat(c)\n }\n\n return\n }\n\n this._knownChats.set(chat.id, chat)\n }\n\n registerUser(user: tl.TypeUser | tl.TypeUser[]): void {\n if (Array.isArray(user)) {\n for (const u of user) {\n this.registerUser(u)\n }\n\n return\n }\n\n this._knownUsers.set(user.id, user)\n\n if (user._ === 'user' && user.self) {\n this._selfId = user.id\n }\n }\n\n getPeers(ids: InputPeerId[]) {\n const users: tl.TypeUser[] = []\n const chats: tl.TypeChat[] = []\n\n for (let id of ids) {\n if (!id) continue\n\n if (typeof id === 'number') {\n id = markedIdToPeer(id)\n }\n\n switch (id._) {\n case 'peerUser': {\n const user = this._knownUsers.get(id.userId)\n if (!user) throw new Error(`Unknown user with ID ${id.userId}`)\n\n users.push(user)\n break\n }\n case 'peerChat': {\n const chat = this._knownChats.get(id.chatId)\n if (!chat) throw new Error(`Unknown chat with ID ${id.chatId}`)\n\n chats.push(chat)\n break\n }\n case 'peerChannel': {\n const chat = this._knownChats.get(id.channelId)\n if (!chat) throw new Error(`Unknown channel with ID ${id.channelId}`)\n\n chats.push(chat)\n break\n }\n }\n }\n\n return { users, chats }\n }\n\n // method calls intercepting //\n\n private _onRawMessage?: (data: Uint8Array) => void\n onRawMessage(fn: (data: Uint8Array) => void): void {\n this._onRawMessage = fn\n }\n\n // eslint-disable-next-line func-call-spacing\n private _responders = new Map<string, (data: unknown) => unknown>()\n\n addResponder<T extends tl.RpcMethod['_']>(responders: InputResponder<T>): void {\n if (Array.isArray(responders)) {\n for (const responder of responders) {\n this.addResponder(responder as InputResponder<tl.RpcMethod['_']>)\n }\n\n return\n }\n\n if (typeof responders === 'function') {\n responders = responders(this)\n }\n\n const [method, responder] = responders\n this.respondWith(method, responder)\n }\n\n respondWith<T extends tl.RpcMethod['_']>(\n method: T,\n response: tl.RpcCallReturn[T] | ((data: tl.FindByName<tl.RpcMethod, T>) => tl.RpcCallReturn[T]),\n ) {\n if (typeof response !== 'function') {\n const res = response\n response = () => res\n }\n\n // eslint-disable-next-line\n this._responders.set(method, response as any)\n }\n\n async call<T extends tl.RpcMethod>(\n message: MustEqual<T, tl.RpcMethod>,\n params?: RpcCallOptions,\n ): Promise<tl.RpcCallReturn[T['_']]> {\n if (this._responders.has(message._)) {\n // eslint-disable-next-line\n return Promise.resolve(this._responders.get(message._)!(message)) as any\n }\n\n return super.call(message, params)\n }\n\n // some fake updates mechanism //\n\n private _fakeMessageBoxes = new Map<number, MessageBox>()\n private _lastQts = 0\n private _lastDate = Math.floor(Date.now() / 1000)\n private _lastSeq = 0\n\n getMessageBox(chatId = 0): MessageBox {\n const state = this._fakeMessageBoxes.get(chatId)\n\n if (!state) {\n const newState = { pts: 0, lastMessageId: 0 }\n this._fakeMessageBoxes.set(chatId, newState)\n\n return newState\n }\n\n return state\n }\n\n getNextMessageId(chatId = 0) {\n const state = this.getMessageBox(chatId)\n\n const nextId = state.lastMessageId + 1\n state.lastMessageId = nextId\n\n return nextId\n }\n\n getNextPts(chatId = 0, count = 1) {\n const state = this.getMessageBox(chatId)\n\n const nextPts = state.pts + count\n state.pts = nextPts\n\n return nextPts\n }\n\n getNextQts() {\n return this._lastQts++\n }\n\n getNextDate() {\n return (this._lastDate = Math.floor(Date.now() / 1000))\n }\n\n createStubUpdates(params: {\n updates: tl.TypeUpdate[]\n peers?: (number | tl.TypePeer)[]\n seq?: number\n seqCount?: number\n }): tl.TypeUpdates {\n const { peers, updates, seq = 0, seqCount = 1 } = params\n\n const { users, chats } = this.getPeers(peers ?? [])\n\n const seqStart = seq - seqCount + 1\n\n if (seq !== 0) {\n this._lastSeq = seq + seqCount\n }\n\n if (seqStart !== seq) {\n return {\n _: 'updatesCombined',\n updates,\n users,\n chats,\n date: this.getNextDate(),\n seq,\n seqStart,\n }\n }\n\n return {\n _: 'updates',\n updates,\n users,\n chats,\n date: this.getNextDate(),\n seq,\n }\n }\n\n // helpers //\n\n async connectAndWait() {\n await this.connect()\n await new Promise((resolve) => this.once('usable', resolve))\n }\n\n async with(fn: () => MaybeAsync<void>): Promise<void> {\n await this.connectAndWait()\n\n let error: unknown\n\n this.onError((err) => {\n error = err\n })\n\n try {\n await fn()\n } catch (e) {\n error = e\n }\n\n await this.close()\n\n if (error) {\n // eslint-disable-next-line @typescript-eslint/no-throw-literal\n throw error\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseTelegramClient, BaseTelegramClientOptions, MaybeAsync, MustEqual, RpcCallOptions, tl } from '@mtcute/core'\n\nimport { StubMemoryTelegramStorage } from './storage.js'\nimport { StubTelegramTransport } from './transport.js'\nimport { InputResponder } from './types.js'\nimport { markedIdToPeer } from './utils.js'\n\ninterface MessageBox {\n pts: number\n lastMessageId: number\n}\n\ntype InputPeerId = number | tl.TypePeer | false | undefined\n\nexport class StubTelegramClient extends BaseTelegramClient {\n constructor(params?: Partial<BaseTelegramClientOptions>) {\n const storage = new StubMemoryTelegramStorage({\n hasKeys: true,\n hasTempKeys: true,\n })\n\n super({\n apiId: 0,\n apiHash: '',\n logLevel: 0,\n storage,\n transport: () => {\n const transport = new StubTelegramTransport({\n onMessage: (data) => {\n if (!this._onRawMessage) {\n if (this._responders.size) {\n this._emitError(new Error('Unexpected outgoing message'))\n }\n\n return\n }\n\n const dcId = transport._currentDc!.id\n const key = storage.getAuthKeyFor(dcId)\n\n if (key) {\n this._onRawMessage(storage.decryptOutgoingMessage(transport._crypto, data, dcId))\n }\n },\n })\n\n return transport\n },\n ...params,\n })\n }\n\n /**\n * Create a fake client that may not actually be used for API calls\n *\n * Useful for testing \"offline\" methods\n */\n static offline() {\n const client = new StubTelegramClient()\n\n client.call = (obj) => {\n throw new Error(`Expected offline client to not make any API calls (method called: ${obj._})`)\n }\n\n return client\n }\n\n // some fake peers handling //\n\n readonly _knownChats = new Map<number, tl.TypeChat>()\n readonly _knownUsers = new Map<number, tl.TypeUser>()\n _selfId = 0\n\n async registerPeers(...peers: (tl.TypeUser | tl.TypeChat)[]): Promise<void> {\n for (const peer of peers) {\n if (tl.isAnyUser(peer)) {\n this._knownUsers.set(peer.id, peer)\n } else {\n this._knownChats.set(peer.id, peer)\n }\n\n await this._cachePeersFrom(peer)\n }\n }\n\n getPeers(ids: InputPeerId[]) {\n const users: tl.TypeUser[] = []\n const chats: tl.TypeChat[] = []\n\n for (let id of ids) {\n if (!id) continue\n\n if (typeof id === 'number') {\n id = markedIdToPeer(id)\n }\n\n switch (id._) {\n case 'peerUser': {\n const user = this._knownUsers.get(id.userId)\n if (!user) throw new Error(`Unknown user with ID ${id.userId}`)\n\n users.push(user)\n break\n }\n case 'peerChat': {\n const chat = this._knownChats.get(id.chatId)\n if (!chat) throw new Error(`Unknown chat with ID ${id.chatId}`)\n\n chats.push(chat)\n break\n }\n case 'peerChannel': {\n const chat = this._knownChats.get(id.channelId)\n if (!chat) throw new Error(`Unknown channel with ID ${id.channelId}`)\n\n chats.push(chat)\n break\n }\n }\n }\n\n return { users, chats }\n }\n\n // method calls intercepting //\n\n private _onRawMessage?: (data: Uint8Array) => void\n onRawMessage(fn: (data: Uint8Array) => void): void {\n this._onRawMessage = fn\n }\n\n // eslint-disable-next-line func-call-spacing\n private _responders = new Map<string, (data: unknown) => unknown>()\n\n addResponder<T extends tl.RpcMethod['_']>(responders: InputResponder<T>): void {\n if (Array.isArray(responders)) {\n for (const responder of responders) {\n this.addResponder(responder as InputResponder<tl.RpcMethod['_']>)\n }\n\n return\n }\n\n if (typeof responders === 'function') {\n responders = responders(this)\n }\n\n const [method, responder] = responders\n this.respondWith(method, responder)\n }\n\n respondWith<\n T extends tl.RpcMethod['_'],\n Fn extends(data: tl.FindByName<tl.RpcMethod, T>) => MaybeAsync<tl.RpcCallReturn[T]>,\n >(method: T, response: Fn): Fn {\n // eslint-disable-next-line\n this._responders.set(method, response as any)\n\n return response\n }\n\n async call<T extends tl.RpcMethod>(\n message: MustEqual<T, tl.RpcMethod>,\n params?: RpcCallOptions,\n ): Promise<tl.RpcCallReturn[T['_']]> {\n if (this._responders.has(message._)) {\n // eslint-disable-next-line\n return Promise.resolve(this._responders.get(message._)!(message)) as any\n }\n\n return super.call(message, params)\n }\n\n // some fake updates mechanism //\n\n private _fakeMessageBoxes = new Map<number, MessageBox>()\n private _lastQts = 0\n private _lastDate = Math.floor(Date.now() / 1000)\n private _lastSeq = 0\n\n getMessageBox(chatId = 0): MessageBox {\n const state = this._fakeMessageBoxes.get(chatId)\n\n if (!state) {\n const newState = { pts: 0, lastMessageId: 0 }\n this._fakeMessageBoxes.set(chatId, newState)\n\n return newState\n }\n\n return state\n }\n\n getNextMessageId(chatId = 0) {\n const state = this.getMessageBox(chatId)\n\n const nextId = state.lastMessageId + 1\n state.lastMessageId = nextId\n\n return nextId\n }\n\n getNextPts(chatId = 0, count = 1) {\n const state = this.getMessageBox(chatId)\n\n const nextPts = state.pts + count\n state.pts = nextPts\n\n return nextPts\n }\n\n getNextQts() {\n return this._lastQts++\n }\n\n getNextDate() {\n return (this._lastDate = Math.floor(Date.now() / 1000))\n }\n\n createStubUpdates(params: {\n updates: tl.TypeUpdate[]\n peers?: (number | tl.TypePeer)[]\n seq?: number\n seqCount?: number\n }): tl.TypeUpdates {\n const { peers, updates, seq = 0, seqCount = 1 } = params\n\n const { users, chats } = this.getPeers(peers ?? [])\n\n const seqStart = seq - seqCount + 1\n\n if (seq !== 0) {\n this._lastSeq = seq + seqCount\n }\n\n if (seqStart !== seq) {\n return {\n _: 'updatesCombined',\n updates,\n users,\n chats,\n date: this.getNextDate(),\n seq,\n seqStart,\n }\n }\n\n return {\n _: 'updates',\n updates,\n users,\n chats,\n date: this.getNextDate(),\n seq,\n }\n }\n\n // helpers //\n\n async connectAndWait() {\n await this.connect()\n await new Promise((resolve) => this.once('usable', resolve))\n }\n\n async with(fn: () => MaybeAsync<void>): Promise<void> {\n await this.connectAndWait()\n\n let error: unknown\n\n this.onError((err) => {\n error = err\n })\n\n try {\n await fn()\n } catch (e) {\n error = e\n }\n\n await this.close()\n\n if (error) {\n // eslint-disable-next-line @typescript-eslint/no-throw-literal\n throw error\n }\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/* eslint-disable no-restricted-globals */
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { StubTelegramClient } from './client.js';
|
|
4
|
+
import { createStub } from './stub.js';
|
|
5
|
+
describe('client stub', () => {
|
|
6
|
+
it('should correctly intercept rpc calls', async () => {
|
|
7
|
+
const client = new StubTelegramClient();
|
|
8
|
+
const stubConfig = createStub('config');
|
|
9
|
+
client.respondWith('help.getConfig', () => stubConfig);
|
|
10
|
+
await client.with(async () => {
|
|
11
|
+
const result = await client.call({ _: 'help.getConfig' });
|
|
12
|
+
expect(result).toEqual(stubConfig);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
it('should correctly decrypt intercepted raw messages', async () => {
|
|
16
|
+
const log = [];
|
|
17
|
+
const client = new StubTelegramClient();
|
|
18
|
+
client.onRawMessage((msg) => {
|
|
19
|
+
log.push(`message ctor=${Buffer.from(msg.slice(0, 4)).toString('hex')}`);
|
|
20
|
+
client.close().catch(() => { });
|
|
21
|
+
});
|
|
22
|
+
await client.with(async () => {
|
|
23
|
+
await client.call({ _: 'help.getConfig' }).catch(() => { }); // ignore "client closed" error
|
|
24
|
+
expect(log).toEqual([
|
|
25
|
+
'message ctor=dcf8f173', // msg_container
|
|
26
|
+
]);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
//# sourceMappingURL=client.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.test.js","sourceRoot":"","sources":["../../src/client.test.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAE7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAEtC,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IACzB,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QAClD,MAAM,MAAM,GAAG,IAAI,kBAAkB,EAAE,CAAA;QAEvC,MAAM,UAAU,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAA;QACvC,MAAM,CAAC,WAAW,CAAC,gBAAgB,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,CAAA;QAEtD,MAAM,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;YACzB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,gBAAgB,EAAE,CAAC,CAAA;YACzD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;QACtC,CAAC,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,GAAG,GAAa,EAAE,CAAA;QAExB,MAAM,MAAM,GAAG,IAAI,kBAAkB,EAAE,CAAA;QAEvC,MAAM,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,EAAE;YACxB,GAAG,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;YACxE,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAClC,CAAC,CAAC,CAAA;QAEF,MAAM,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;YACzB,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,gBAAgB,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA,CAAC,+BAA+B;YAE1F,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;gBAChB,uBAAuB,EAAE,gBAAgB;aAC5C,CAAC,CAAA;QACN,CAAC,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;AACN,CAAC,CAAC,CAAA","sourcesContent":["/* eslint-disable no-restricted-globals */\nimport { describe, expect, it } from 'vitest'\n\nimport { StubTelegramClient } from './client.js'\nimport { createStub } from './stub.js'\n\ndescribe('client stub', () => {\n it('should correctly intercept rpc calls', async () => {\n const client = new StubTelegramClient()\n\n const stubConfig = createStub('config')\n client.respondWith('help.getConfig', () => stubConfig)\n\n await client.with(async () => {\n const result = await client.call({ _: 'help.getConfig' })\n expect(result).toEqual(stubConfig)\n })\n })\n\n it('should correctly decrypt intercepted raw messages', async () => {\n const log: string[] = []\n\n const client = new StubTelegramClient()\n\n client.onRawMessage((msg) => {\n log.push(`message ctor=${Buffer.from(msg.slice(0, 4)).toString('hex')}`)\n client.close().catch(() => {})\n })\n\n await client.with(async () => {\n await client.call({ _: 'help.getConfig' }).catch(() => {}) // ignore \"client closed\" error\n\n expect(log).toEqual([\n 'message ctor=dcf8f173', // msg_container\n ])\n })\n })\n})\n"]}
|
package/esm/crypto.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ICryptoProvider } from '@mtcute/core/utils.js';
|
|
2
|
+
export declare function withFakeRandom(provider: ICryptoProvider, source?: string): ICryptoProvider;
|
|
3
|
+
export declare function useFakeMathRandom(source?: string): void;
|
|
4
|
+
export declare function defaultTestCryptoProvider(source?: string): Promise<ICryptoProvider>;
|
|
5
|
+
export declare function testCryptoProvider(c: ICryptoProvider): void;
|
|
6
|
+
export declare function u8HexDecode(hex: string): Uint8Array;
|
package/esm/crypto.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/* eslint-disable no-restricted-globals */
|
|
2
|
+
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { gzipSync, inflateSync } from 'zlib';
|
|
4
|
+
import { dataViewFromBuffer, defaultCryptoProviderFactory, hexDecodeToBuffer, hexEncode, utf8EncodeToBuffer, } from '@mtcute/core/utils.js';
|
|
5
|
+
// some random 1024 bytes of entropy
|
|
6
|
+
const DEFAULT_ENTROPY = `
|
|
7
|
+
29afd26df40fb8ed10b6b4ad6d56ef5df9453f88e6ee6adb6e0544ba635dc6a8a990c9b8b980c343936b33fa7f97bae025102532233abb269c489920ef99021b
|
|
8
|
+
259ce3a2c964c5c8972b4a84ff96f3375a94b535a9468f2896e2080ac7a32ed58e910474a4b02415e07671cbb5bdd58a5dd26fd137c4c98b8c346571fae6ead3
|
|
9
|
+
9dfd612bd6b480b6723433f5218e9d6e271591153fb3ffefc089f7e848d3f4633459fff66b33cf939e5655813149fa34be8625f9bc4814d1ee6cf40e4d0de229
|
|
10
|
+
1aa22e68c8ad8cc698103734f9aaf79f2bdc052a787a7a9b3629d1ed38750f88cb0481c0ba30a9c611672f9a4d1dc02637abb4e98913ee810a3b152d3d75f25d
|
|
11
|
+
7efdc263c08833569968b1771ebbe843d187e2c917d9ad8e8865e44b69f7b74d72ab86a4ef1891dce196ee11a7c9d7d8074fc0450e745bd3a827d77bb0820b90
|
|
12
|
+
3055dc15f0abd897ea740a99606b64d28968d770b5e43492ddbf07a7c75104d3e522be9b72050c0fdae8412cdf49014be21105b87a06cb7202dd580387adc007
|
|
13
|
+
6280d98b015a1a413819d817f007939d1490467a1ef85a345584c7e594bb729c12a1233f806e515e7088360219dfa109264310ba84777b93eb1ad3c40727a25a
|
|
14
|
+
a5d9cdd6748c6ab2ca0bd4daa2ba8225bce2b066a163bcacf05609fc84055bb86a4742c28addd7d7ab8d87b64cfde0b3f4b3bc8e05f3d0a1a2fadb294860e099
|
|
15
|
+
a10b3721b0d5b28918b8fb49a18a82a0fde6680a64ed915637805e35ffe8b2c1d4177ec10d10eaaf24425e0351b6a89e794944e1aa82eb5c0210a37da66cccac
|
|
16
|
+
895398cf915a8aa141f611521fc258514a99c02721113942c66f2c9a8f9601ff0044a953d17a47b07ad1b5f8725cc020a1a5239be65db0a43d42c206903740f0
|
|
17
|
+
27c3f749ecfff2e646570118cd54db2fec392b44d8eb8377309f3e4d164dbc0530914b117b9d278b06db8359d97442d4dcbcaff93cd9a08a6b06a5ba8725d0d7
|
|
18
|
+
06b313a5d792be254d33e087b7a4fafcdf819941b9bec4c6057d4c050bd01eb243efd4e6b707281b127820a2b734c6d8f6b2131bf0b5b215c7a798ff3fe90ceb
|
|
19
|
+
da91539fcc7b03d2b8b1381bd6023fff20278344ad944d364ba684842db3901c346335f0d455eda414f99c1e794a86aa3a90bcc6e085eecb0b4bf61198d16ed3
|
|
20
|
+
89cfa495f977a37a51502b2f60649f2efd7d89c757b6366776ba4c0612017bf1fbfc682dd62e9960d39cbea854d2dcc708b1db5d268192954d13ee72c0bb1bd8
|
|
21
|
+
558a3cf3b02b1cd795b40f7a57780391bb8724883d3f7764846c3823e165b3f8c025f59d896905f9a955478586ce57f820d958a01aa59a4cace7ecdf125df334
|
|
22
|
+
fa3de8e50aac96c1275591a1221c32a60a1513370a33a228e00894341b10cf44a6ae6ac250d17a364e956ab1a17b068df3fb2d5b5a672d8a409eeb8b6ca1ade6
|
|
23
|
+
`.replace(/\s/g, '');
|
|
24
|
+
export function withFakeRandom(provider, source = DEFAULT_ENTROPY) {
|
|
25
|
+
const sourceBytes = hexDecodeToBuffer(source);
|
|
26
|
+
let offset = 0;
|
|
27
|
+
function getRandomValues(buf) {
|
|
28
|
+
if (offset + buf.length > sourceBytes.length) {
|
|
29
|
+
throw new Error('not enough entropy');
|
|
30
|
+
}
|
|
31
|
+
buf.set(sourceBytes.subarray(offset, offset + buf.length));
|
|
32
|
+
offset += buf.length;
|
|
33
|
+
}
|
|
34
|
+
provider.randomFill = getRandomValues;
|
|
35
|
+
return provider;
|
|
36
|
+
}
|
|
37
|
+
export function useFakeMathRandom(source = DEFAULT_ENTROPY) {
|
|
38
|
+
beforeEach(() => {
|
|
39
|
+
const sourceBytes = hexDecodeToBuffer(source);
|
|
40
|
+
let offset = 0;
|
|
41
|
+
vi.spyOn(globalThis.Math, 'random').mockImplementation(() => {
|
|
42
|
+
const ret = dataViewFromBuffer(sourceBytes).getUint32(offset, true) / 0xffffffff;
|
|
43
|
+
offset += 4;
|
|
44
|
+
return ret;
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
afterEach(() => {
|
|
48
|
+
vi.spyOn(globalThis.Math, 'random').mockRestore();
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
export async function defaultTestCryptoProvider(source = DEFAULT_ENTROPY) {
|
|
52
|
+
const prov = withFakeRandom(defaultCryptoProviderFactory(), source);
|
|
53
|
+
await prov.initialize?.();
|
|
54
|
+
return prov;
|
|
55
|
+
}
|
|
56
|
+
export function testCryptoProvider(c) {
|
|
57
|
+
beforeAll(() => c.initialize?.());
|
|
58
|
+
it('should calculate sha1', () => {
|
|
59
|
+
expect(hexEncode(c.sha1(utf8EncodeToBuffer('')))).to.eq('da39a3ee5e6b4b0d3255bfef95601890afd80709');
|
|
60
|
+
expect(hexEncode(c.sha1(utf8EncodeToBuffer('hello')))).to.eq('aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d');
|
|
61
|
+
expect(hexEncode(c.sha1(hexDecodeToBuffer('aebb1f')))).to.eq('62849d15c5dea495916c5eea8dba5f9551288850');
|
|
62
|
+
});
|
|
63
|
+
it('should calculate sha256', () => {
|
|
64
|
+
expect(hexEncode(c.sha256(utf8EncodeToBuffer('')))).to.eq('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855');
|
|
65
|
+
expect(hexEncode(c.sha256(utf8EncodeToBuffer('hello')))).to.eq('2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824');
|
|
66
|
+
expect(hexEncode(c.sha256(hexDecodeToBuffer('aebb1f')))).to.eq('2d29658aba48f2b286fe8bbddb931b7ad297e5adb5b9a6fc3aab67ef7fbf4e80');
|
|
67
|
+
});
|
|
68
|
+
it('should calculate hmac-sha256', async () => {
|
|
69
|
+
const key = hexDecodeToBuffer('aaeeff');
|
|
70
|
+
expect(hexEncode(await c.hmacSha256(utf8EncodeToBuffer(''), key))).to.eq('642711307c9e4437df09d6ebaa6bdc1b3a810c7f15c50fd1d0f8d7d5490f44dd');
|
|
71
|
+
expect(hexEncode(await c.hmacSha256(utf8EncodeToBuffer('hello'), key))).to.eq('39b00bab151f9868e6501655c580b5542954711181243474d46b894703b1c1c2');
|
|
72
|
+
expect(hexEncode(await c.hmacSha256(hexDecodeToBuffer('aebb1f'), key))).to.eq('a3a7273871808711cab17aba14f58e96f63f3ccfc5097d206f0f00ead2c3dd35');
|
|
73
|
+
});
|
|
74
|
+
it('should derive pbkdf2 key', async () => {
|
|
75
|
+
expect(hexEncode(await c.pbkdf2(utf8EncodeToBuffer('pbkdf2 test'), utf8EncodeToBuffer('some salt'), 10))).to.eq('e43276cfa27f135f261cec8ddcf593fd74ec251038e459c165461f2308f3a7235e0744ee1aed9710b00db28d1a2112e20fea3601c60e770ac57ffe6b33ca8be1');
|
|
76
|
+
});
|
|
77
|
+
it('should encrypt and decrypt aes-ctr', () => {
|
|
78
|
+
let aes = c.createAesCtr(hexDecodeToBuffer('d450aae0bf0060a4af1044886b42a13f7c506b35255d134a7e87ab3f23a9493b'), hexDecodeToBuffer('0182de2bd789c295c3c6c875c5e9e190'), true);
|
|
79
|
+
const data = hexDecodeToBuffer('7baae571e4c2f4cfadb1931d5923aca7');
|
|
80
|
+
expect(hexEncode(aes.process(data))).eq('df5647dbb70bc393f2fb05b72f42286f');
|
|
81
|
+
expect(hexEncode(aes.process(data))).eq('3917147082672516b3177150129bc579');
|
|
82
|
+
expect(hexEncode(aes.process(data))).eq('2a7a9089270a5de45d5e3dd399cac725');
|
|
83
|
+
expect(hexEncode(aes.process(data))).eq('56d085217771398ac13583de4d677dd8');
|
|
84
|
+
expect(hexEncode(aes.process(data))).eq('cc639b488126cf36e79c4515e8012b92');
|
|
85
|
+
expect(hexEncode(aes.process(data))).eq('01384d100646cd562cc5586ec3f8f8c4');
|
|
86
|
+
aes.close?.();
|
|
87
|
+
aes = c.createAesCtr(hexDecodeToBuffer('d450aae0bf0060a4af1044886b42a13f7c506b35255d134a7e87ab3f23a9493b'), hexDecodeToBuffer('0182de2bd789c295c3c6c875c5e9e190'), false);
|
|
88
|
+
expect(hexEncode(aes.process(hexDecodeToBuffer('df5647dbb70bc393f2fb05b72f42286f')))).eq(hexEncode(data));
|
|
89
|
+
expect(hexEncode(aes.process(hexDecodeToBuffer('3917147082672516b3177150129bc579')))).eq(hexEncode(data));
|
|
90
|
+
expect(hexEncode(aes.process(hexDecodeToBuffer('2a7a9089270a5de45d5e3dd399cac725')))).eq(hexEncode(data));
|
|
91
|
+
expect(hexEncode(aes.process(hexDecodeToBuffer('56d085217771398ac13583de4d677dd8')))).eq(hexEncode(data));
|
|
92
|
+
expect(hexEncode(aes.process(hexDecodeToBuffer('cc639b488126cf36e79c4515e8012b92')))).eq(hexEncode(data));
|
|
93
|
+
expect(hexEncode(aes.process(hexDecodeToBuffer('01384d100646cd562cc5586ec3f8f8c4')))).eq(hexEncode(data));
|
|
94
|
+
aes.close?.();
|
|
95
|
+
});
|
|
96
|
+
it('should encrypt and decrypt aes-ige', () => {
|
|
97
|
+
const aes = c.createAesIge(hexDecodeToBuffer('5468697320697320616E20696D706C655468697320697320616E20696D706C65'), hexDecodeToBuffer('6D656E746174696F6E206F6620494745206D6F646520666F72204F70656E5353'));
|
|
98
|
+
expect(hexEncode(aes.encrypt(hexDecodeToBuffer('99706487a1cde613bc6de0b6f24b1c7aa448c8b9c3403e3467a8cad89340f53b')))).to.eq('792ea8ae577b1a66cb3bd92679b8030ca54ee631976bd3a04547fdcb4639fa69');
|
|
99
|
+
expect(hexEncode(aes.decrypt(hexDecodeToBuffer('792ea8ae577b1a66cb3bd92679b8030ca54ee631976bd3a04547fdcb4639fa69')))).to.eq('99706487a1cde613bc6de0b6f24b1c7aa448c8b9c3403e3467a8cad89340f53b');
|
|
100
|
+
});
|
|
101
|
+
it('should decompose PQ to prime factors P and Q', async () => {
|
|
102
|
+
const testFactorization = async (pq, p, q) => {
|
|
103
|
+
const [p1, q1] = await c.factorizePQ(hexDecodeToBuffer(pq));
|
|
104
|
+
expect(hexEncode(p1)).eq(p.toLowerCase());
|
|
105
|
+
expect(hexEncode(q1)).eq(q.toLowerCase());
|
|
106
|
+
};
|
|
107
|
+
// from samples at https://core.telegram.org/mtproto/samples-auth_key
|
|
108
|
+
await testFactorization('17ED48941A08F981', '494C553B', '53911073');
|
|
109
|
+
// random example
|
|
110
|
+
await testFactorization('14fcab4dfc861f45', '494c5c99', '494c778d');
|
|
111
|
+
},
|
|
112
|
+
// since PQ factorization relies on RNG, it may take a while (or may not!)
|
|
113
|
+
{ timeout: 10000 });
|
|
114
|
+
it('should correctly gzip', () => {
|
|
115
|
+
const data = new Uint8Array(1000).fill(0x42);
|
|
116
|
+
const compressed = c.gzip(data, 100);
|
|
117
|
+
expect(compressed).not.toBeNull();
|
|
118
|
+
const decompressed = inflateSync(compressed);
|
|
119
|
+
expect(compressed.length).toBeLessThan(data.length);
|
|
120
|
+
// eslint-disable-next-line no-restricted-globals
|
|
121
|
+
expect(decompressed).toEqual(Buffer.from(data));
|
|
122
|
+
});
|
|
123
|
+
it('should correctly gunzip', () => {
|
|
124
|
+
const data = new Uint8Array(1000).fill(0x42);
|
|
125
|
+
const compressed = gzipSync(data);
|
|
126
|
+
const decompressed = c.gunzip(compressed);
|
|
127
|
+
// eslint-disable-next-line no-restricted-globals
|
|
128
|
+
expect(Buffer.from(decompressed)).toEqual(Buffer.from(data));
|
|
129
|
+
});
|
|
130
|
+
describe('randomBytes', () => {
|
|
131
|
+
it('should return exactly N bytes', () => {
|
|
132
|
+
expect(c.randomBytes(0).length).eq(0);
|
|
133
|
+
expect(c.randomBytes(5).length).eq(5);
|
|
134
|
+
expect(c.randomBytes(10).length).eq(10);
|
|
135
|
+
expect(c.randomBytes(256).length).eq(256);
|
|
136
|
+
});
|
|
137
|
+
it('should not be deterministic', () => {
|
|
138
|
+
expect([...c.randomBytes(8)]).not.eql([...c.randomBytes(8)]);
|
|
139
|
+
});
|
|
140
|
+
it('should use randomFill', () => {
|
|
141
|
+
const spy = vi.spyOn(c, 'randomFill');
|
|
142
|
+
c.randomBytes(8);
|
|
143
|
+
expect(spy).toHaveBeenCalled();
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
export function u8HexDecode(hex) {
|
|
148
|
+
const buf = hexDecodeToBuffer(hex);
|
|
149
|
+
if (Buffer.isBuffer(buf)) {
|
|
150
|
+
return new Uint8Array(buf);
|
|
151
|
+
}
|
|
152
|
+
return buf;
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/crypto.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AACnF,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,MAAM,CAAA;AAE5C,OAAO,EACH,kBAAkB,EAClB,4BAA4B,EAC5B,iBAAiB,EACjB,SAAS,EAET,kBAAkB,GACrB,MAAM,uBAAuB,CAAA;AAE9B,oCAAoC;AACpC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;CAiBvB,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;AAEpB,MAAM,UAAU,cAAc,CAAC,QAAyB,EAAE,MAAM,GAAG,eAAe;IAC9E,MAAM,WAAW,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAA;IAC7C,IAAI,MAAM,GAAG,CAAC,CAAA;IAEd,SAAS,eAAe,CAAC,GAAe;QACpC,IAAI,MAAM,GAAG,GAAG,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,EAAE;YAC1C,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAA;SACxC;QAED,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;QAC1D,MAAM,IAAI,GAAG,CAAC,MAAM,CAAA;IACxB,CAAC;IAED,QAAQ,CAAC,UAAU,GAAG,eAAe,CAAA;IAErC,OAAO,QAAQ,CAAA;AACnB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAM,GAAG,eAAe;IACtD,UAAU,CAAC,GAAG,EAAE;QACZ,MAAM,WAAW,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAA;QAC7C,IAAI,MAAM,GAAG,CAAC,CAAA;QAEd,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE;YACxD,MAAM,GAAG,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,UAAU,CAAA;YAChF,MAAM,IAAI,CAAC,CAAA;YAEX,OAAO,GAAG,CAAA;QACd,CAAC,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;IACF,SAAS,CAAC,GAAG,EAAE;QACX,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAA;IACrD,CAAC,CAAC,CAAA;AACN,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,MAAM,GAAG,eAAe;IACpE,MAAM,IAAI,GAAG,cAAc,CAAC,4BAA4B,EAAE,EAAE,MAAM,CAAC,CAAA;IACnE,MAAM,IAAI,CAAC,UAAU,EAAE,EAAE,CAAA;IAEzB,OAAO,IAAI,CAAA;AACf,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,CAAkB;IACjD,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;IAEjC,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,0CAA0C,CAAC,CAAA;QACnG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,0CAA0C,CAAC,CAAA;QACxG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,0CAA0C,CAAC,CAAA;IAC5G,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QAC/B,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CACrD,kEAAkE,CACrE,CAAA;QACD,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAC1D,kEAAkE,CACrE,CAAA;QACD,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAC1D,kEAAkE,CACrE,CAAA;IACL,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;QAC1C,MAAM,GAAG,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAA;QAEvC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CACpE,kEAAkE,CACrE,CAAA;QACD,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CACzE,kEAAkE,CACrE,CAAA;QACD,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,iBAAiB,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CACzE,kEAAkE,CACrE,CAAA;IACL,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;QACtC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,aAAa,CAAC,EAAE,kBAAkB,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAC3G,kIAAkI,CACrI,CAAA;IACL,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC1C,IAAI,GAAG,GAAG,CAAC,CAAC,YAAY,CACpB,iBAAiB,CAAC,kEAAkE,CAAC,EACrF,iBAAiB,CAAC,kCAAkC,CAAC,EACrD,IAAI,CACP,CAAA;QAED,MAAM,IAAI,GAAG,iBAAiB,CAAC,kCAAkC,CAAC,CAAA;QAClE,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,kCAAkC,CAAC,CAAA;QAC3E,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,kCAAkC,CAAC,CAAA;QAC3E,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,kCAAkC,CAAC,CAAA;QAC3E,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,kCAAkC,CAAC,CAAA;QAC3E,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,kCAAkC,CAAC,CAAA;QAC3E,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,kCAAkC,CAAC,CAAA;QAE3E,GAAG,CAAC,KAAK,EAAE,EAAE,CAAA;QACb,GAAG,GAAG,CAAC,CAAC,YAAY,CAChB,iBAAiB,CAAC,kEAAkE,CAAC,EACrF,iBAAiB,CAAC,kCAAkC,CAAC,EACrD,KAAK,CACR,CAAA;QAED,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,kCAAkC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;QACzG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,kCAAkC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;QACzG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,kCAAkC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;QACzG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,kCAAkC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;QACzG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,kCAAkC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;QACzG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,kCAAkC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;QAEzG,GAAG,CAAC,KAAK,EAAE,EAAE,CAAA;IACjB,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC1C,MAAM,GAAG,GAAG,CAAC,CAAC,YAAY,CACtB,iBAAiB,CAAC,kEAAkE,CAAC,EACrF,iBAAiB,CAAC,kEAAkE,CAAC,CACxF,CAAA;QACD,MAAM,CACF,SAAS,CACL,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,kEAAkE,CAAC,CAAC,CACrG,CACJ,CAAC,EAAE,CAAC,EAAE,CAAC,kEAAkE,CAAC,CAAA;QAC3E,MAAM,CACF,SAAS,CACL,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,kEAAkE,CAAC,CAAC,CACrG,CACJ,CAAC,EAAE,CAAC,EAAE,CAAC,kEAAkE,CAAC,CAAA;IAC/E,CAAC,CAAC,CAAA;IAEF,EAAE,CACE,8CAA8C,EAC9C,KAAK,IAAI,EAAE;QACP,MAAM,iBAAiB,GAAG,KAAK,EAAE,EAAU,EAAE,CAAS,EAAE,CAAS,EAAE,EAAE;YACjE,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,WAAW,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAA;YAC3D,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAA;YACzC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAA;QAC7C,CAAC,CAAA;QAED,qEAAqE;QACrE,MAAM,iBAAiB,CAAC,kBAAkB,EAAE,UAAU,EAAE,UAAU,CAAC,CAAA;QACnE,iBAAiB;QACjB,MAAM,iBAAiB,CAAC,kBAAkB,EAAE,UAAU,EAAE,UAAU,CAAC,CAAA;IACvE,CAAC;IACD,0EAA0E;IAC1E,EAAE,OAAO,EAAE,KAAK,EAAE,CACrB,CAAA;IAED,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC7B,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAE5C,MAAM,UAAU,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QAEpC,MAAM,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAA;QAEjC,MAAM,YAAY,GAAG,WAAW,CAAC,UAAW,CAAC,CAAA;QAE7C,MAAM,CAAC,UAAW,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACpD,iDAAiD;QACjD,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QAC/B,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAE5C,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;QACjC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;QAEzC,iDAAiD;QACjD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAChE,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QACzB,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;YACrC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;YACrC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;YACrC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;YACvC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;QAC7C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;YACnC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAChE,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;YAC7B,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAA;YACrC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;YAEhB,MAAM,CAAC,GAAG,CAAC,CAAC,gBAAgB,EAAE,CAAA;QAClC,CAAC,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;AACN,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW;IACnC,MAAM,GAAG,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAA;IAElC,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;QACtB,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,CAAA;KAC7B;IAED,OAAO,GAAG,CAAA;AACd,CAAC","sourcesContent":["/* eslint-disable no-restricted-globals */\nimport { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { gzipSync, inflateSync } from 'zlib'\n\nimport {\n dataViewFromBuffer,\n defaultCryptoProviderFactory,\n hexDecodeToBuffer,\n hexEncode,\n ICryptoProvider,\n utf8EncodeToBuffer,\n} from '@mtcute/core/utils.js'\n\n// some random 1024 bytes of entropy\nconst DEFAULT_ENTROPY = `\n29afd26df40fb8ed10b6b4ad6d56ef5df9453f88e6ee6adb6e0544ba635dc6a8a990c9b8b980c343936b33fa7f97bae025102532233abb269c489920ef99021b\n259ce3a2c964c5c8972b4a84ff96f3375a94b535a9468f2896e2080ac7a32ed58e910474a4b02415e07671cbb5bdd58a5dd26fd137c4c98b8c346571fae6ead3\n9dfd612bd6b480b6723433f5218e9d6e271591153fb3ffefc089f7e848d3f4633459fff66b33cf939e5655813149fa34be8625f9bc4814d1ee6cf40e4d0de229\n1aa22e68c8ad8cc698103734f9aaf79f2bdc052a787a7a9b3629d1ed38750f88cb0481c0ba30a9c611672f9a4d1dc02637abb4e98913ee810a3b152d3d75f25d\n7efdc263c08833569968b1771ebbe843d187e2c917d9ad8e8865e44b69f7b74d72ab86a4ef1891dce196ee11a7c9d7d8074fc0450e745bd3a827d77bb0820b90\n3055dc15f0abd897ea740a99606b64d28968d770b5e43492ddbf07a7c75104d3e522be9b72050c0fdae8412cdf49014be21105b87a06cb7202dd580387adc007\n6280d98b015a1a413819d817f007939d1490467a1ef85a345584c7e594bb729c12a1233f806e515e7088360219dfa109264310ba84777b93eb1ad3c40727a25a\na5d9cdd6748c6ab2ca0bd4daa2ba8225bce2b066a163bcacf05609fc84055bb86a4742c28addd7d7ab8d87b64cfde0b3f4b3bc8e05f3d0a1a2fadb294860e099\na10b3721b0d5b28918b8fb49a18a82a0fde6680a64ed915637805e35ffe8b2c1d4177ec10d10eaaf24425e0351b6a89e794944e1aa82eb5c0210a37da66cccac\n895398cf915a8aa141f611521fc258514a99c02721113942c66f2c9a8f9601ff0044a953d17a47b07ad1b5f8725cc020a1a5239be65db0a43d42c206903740f0\n27c3f749ecfff2e646570118cd54db2fec392b44d8eb8377309f3e4d164dbc0530914b117b9d278b06db8359d97442d4dcbcaff93cd9a08a6b06a5ba8725d0d7\n06b313a5d792be254d33e087b7a4fafcdf819941b9bec4c6057d4c050bd01eb243efd4e6b707281b127820a2b734c6d8f6b2131bf0b5b215c7a798ff3fe90ceb\nda91539fcc7b03d2b8b1381bd6023fff20278344ad944d364ba684842db3901c346335f0d455eda414f99c1e794a86aa3a90bcc6e085eecb0b4bf61198d16ed3\n89cfa495f977a37a51502b2f60649f2efd7d89c757b6366776ba4c0612017bf1fbfc682dd62e9960d39cbea854d2dcc708b1db5d268192954d13ee72c0bb1bd8\n558a3cf3b02b1cd795b40f7a57780391bb8724883d3f7764846c3823e165b3f8c025f59d896905f9a955478586ce57f820d958a01aa59a4cace7ecdf125df334\nfa3de8e50aac96c1275591a1221c32a60a1513370a33a228e00894341b10cf44a6ae6ac250d17a364e956ab1a17b068df3fb2d5b5a672d8a409eeb8b6ca1ade6\n`.replace(/\\s/g, '')\n\nexport function withFakeRandom(provider: ICryptoProvider, source = DEFAULT_ENTROPY): ICryptoProvider {\n const sourceBytes = hexDecodeToBuffer(source)\n let offset = 0\n\n function getRandomValues(buf: Uint8Array) {\n if (offset + buf.length > sourceBytes.length) {\n throw new Error('not enough entropy')\n }\n\n buf.set(sourceBytes.subarray(offset, offset + buf.length))\n offset += buf.length\n }\n\n provider.randomFill = getRandomValues\n\n return provider\n}\n\nexport function useFakeMathRandom(source = DEFAULT_ENTROPY): void {\n beforeEach(() => {\n const sourceBytes = hexDecodeToBuffer(source)\n let offset = 0\n\n vi.spyOn(globalThis.Math, 'random').mockImplementation(() => {\n const ret = dataViewFromBuffer(sourceBytes).getUint32(offset, true) / 0xffffffff\n offset += 4\n\n return ret\n })\n })\n afterEach(() => {\n vi.spyOn(globalThis.Math, 'random').mockRestore()\n })\n}\n\nexport async function defaultTestCryptoProvider(source = DEFAULT_ENTROPY): Promise<ICryptoProvider> {\n const prov = withFakeRandom(defaultCryptoProviderFactory(), source)\n await prov.initialize?.()\n\n return prov\n}\n\nexport function testCryptoProvider(c: ICryptoProvider): void {\n beforeAll(() => c.initialize?.())\n\n it('should calculate sha1', () => {\n expect(hexEncode(c.sha1(utf8EncodeToBuffer('')))).to.eq('da39a3ee5e6b4b0d3255bfef95601890afd80709')\n expect(hexEncode(c.sha1(utf8EncodeToBuffer('hello')))).to.eq('aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d')\n expect(hexEncode(c.sha1(hexDecodeToBuffer('aebb1f')))).to.eq('62849d15c5dea495916c5eea8dba5f9551288850')\n })\n\n it('should calculate sha256', () => {\n expect(hexEncode(c.sha256(utf8EncodeToBuffer('')))).to.eq(\n 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',\n )\n expect(hexEncode(c.sha256(utf8EncodeToBuffer('hello')))).to.eq(\n '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824',\n )\n expect(hexEncode(c.sha256(hexDecodeToBuffer('aebb1f')))).to.eq(\n '2d29658aba48f2b286fe8bbddb931b7ad297e5adb5b9a6fc3aab67ef7fbf4e80',\n )\n })\n\n it('should calculate hmac-sha256', async () => {\n const key = hexDecodeToBuffer('aaeeff')\n\n expect(hexEncode(await c.hmacSha256(utf8EncodeToBuffer(''), key))).to.eq(\n '642711307c9e4437df09d6ebaa6bdc1b3a810c7f15c50fd1d0f8d7d5490f44dd',\n )\n expect(hexEncode(await c.hmacSha256(utf8EncodeToBuffer('hello'), key))).to.eq(\n '39b00bab151f9868e6501655c580b5542954711181243474d46b894703b1c1c2',\n )\n expect(hexEncode(await c.hmacSha256(hexDecodeToBuffer('aebb1f'), key))).to.eq(\n 'a3a7273871808711cab17aba14f58e96f63f3ccfc5097d206f0f00ead2c3dd35',\n )\n })\n\n it('should derive pbkdf2 key', async () => {\n expect(hexEncode(await c.pbkdf2(utf8EncodeToBuffer('pbkdf2 test'), utf8EncodeToBuffer('some salt'), 10))).to.eq(\n 'e43276cfa27f135f261cec8ddcf593fd74ec251038e459c165461f2308f3a7235e0744ee1aed9710b00db28d1a2112e20fea3601c60e770ac57ffe6b33ca8be1',\n )\n })\n\n it('should encrypt and decrypt aes-ctr', () => {\n let aes = c.createAesCtr(\n hexDecodeToBuffer('d450aae0bf0060a4af1044886b42a13f7c506b35255d134a7e87ab3f23a9493b'),\n hexDecodeToBuffer('0182de2bd789c295c3c6c875c5e9e190'),\n true,\n )\n\n const data = hexDecodeToBuffer('7baae571e4c2f4cfadb1931d5923aca7')\n expect(hexEncode(aes.process(data))).eq('df5647dbb70bc393f2fb05b72f42286f')\n expect(hexEncode(aes.process(data))).eq('3917147082672516b3177150129bc579')\n expect(hexEncode(aes.process(data))).eq('2a7a9089270a5de45d5e3dd399cac725')\n expect(hexEncode(aes.process(data))).eq('56d085217771398ac13583de4d677dd8')\n expect(hexEncode(aes.process(data))).eq('cc639b488126cf36e79c4515e8012b92')\n expect(hexEncode(aes.process(data))).eq('01384d100646cd562cc5586ec3f8f8c4')\n\n aes.close?.()\n aes = c.createAesCtr(\n hexDecodeToBuffer('d450aae0bf0060a4af1044886b42a13f7c506b35255d134a7e87ab3f23a9493b'),\n hexDecodeToBuffer('0182de2bd789c295c3c6c875c5e9e190'),\n false,\n )\n\n expect(hexEncode(aes.process(hexDecodeToBuffer('df5647dbb70bc393f2fb05b72f42286f')))).eq(hexEncode(data))\n expect(hexEncode(aes.process(hexDecodeToBuffer('3917147082672516b3177150129bc579')))).eq(hexEncode(data))\n expect(hexEncode(aes.process(hexDecodeToBuffer('2a7a9089270a5de45d5e3dd399cac725')))).eq(hexEncode(data))\n expect(hexEncode(aes.process(hexDecodeToBuffer('56d085217771398ac13583de4d677dd8')))).eq(hexEncode(data))\n expect(hexEncode(aes.process(hexDecodeToBuffer('cc639b488126cf36e79c4515e8012b92')))).eq(hexEncode(data))\n expect(hexEncode(aes.process(hexDecodeToBuffer('01384d100646cd562cc5586ec3f8f8c4')))).eq(hexEncode(data))\n\n aes.close?.()\n })\n\n it('should encrypt and decrypt aes-ige', () => {\n const aes = c.createAesIge(\n hexDecodeToBuffer('5468697320697320616E20696D706C655468697320697320616E20696D706C65'),\n hexDecodeToBuffer('6D656E746174696F6E206F6620494745206D6F646520666F72204F70656E5353'),\n )\n expect(\n hexEncode(\n aes.encrypt(hexDecodeToBuffer('99706487a1cde613bc6de0b6f24b1c7aa448c8b9c3403e3467a8cad89340f53b')),\n ),\n ).to.eq('792ea8ae577b1a66cb3bd92679b8030ca54ee631976bd3a04547fdcb4639fa69')\n expect(\n hexEncode(\n aes.decrypt(hexDecodeToBuffer('792ea8ae577b1a66cb3bd92679b8030ca54ee631976bd3a04547fdcb4639fa69')),\n ),\n ).to.eq('99706487a1cde613bc6de0b6f24b1c7aa448c8b9c3403e3467a8cad89340f53b')\n })\n\n it(\n 'should decompose PQ to prime factors P and Q',\n async () => {\n const testFactorization = async (pq: string, p: string, q: string) => {\n const [p1, q1] = await c.factorizePQ(hexDecodeToBuffer(pq))\n expect(hexEncode(p1)).eq(p.toLowerCase())\n expect(hexEncode(q1)).eq(q.toLowerCase())\n }\n\n // from samples at https://core.telegram.org/mtproto/samples-auth_key\n await testFactorization('17ED48941A08F981', '494C553B', '53911073')\n // random example\n await testFactorization('14fcab4dfc861f45', '494c5c99', '494c778d')\n },\n // since PQ factorization relies on RNG, it may take a while (or may not!)\n { timeout: 10000 },\n )\n\n it('should correctly gzip', () => {\n const data = new Uint8Array(1000).fill(0x42)\n\n const compressed = c.gzip(data, 100)\n\n expect(compressed).not.toBeNull()\n\n const decompressed = inflateSync(compressed!)\n\n expect(compressed!.length).toBeLessThan(data.length)\n // eslint-disable-next-line no-restricted-globals\n expect(decompressed).toEqual(Buffer.from(data))\n })\n\n it('should correctly gunzip', () => {\n const data = new Uint8Array(1000).fill(0x42)\n\n const compressed = gzipSync(data)\n const decompressed = c.gunzip(compressed)\n\n // eslint-disable-next-line no-restricted-globals\n expect(Buffer.from(decompressed)).toEqual(Buffer.from(data))\n })\n\n describe('randomBytes', () => {\n it('should return exactly N bytes', () => {\n expect(c.randomBytes(0).length).eq(0)\n expect(c.randomBytes(5).length).eq(5)\n expect(c.randomBytes(10).length).eq(10)\n expect(c.randomBytes(256).length).eq(256)\n })\n\n it('should not be deterministic', () => {\n expect([...c.randomBytes(8)]).not.eql([...c.randomBytes(8)])\n })\n\n it('should use randomFill', () => {\n const spy = vi.spyOn(c, 'randomFill')\n c.randomBytes(8)\n\n expect(spy).toHaveBeenCalled()\n })\n })\n}\n\nexport function u8HexDecode(hex: string) {\n const buf = hexDecodeToBuffer(hex)\n\n if (Buffer.isBuffer(buf)) {\n return new Uint8Array(buf)\n }\n\n return buf\n}\n"]}
|
package/esm/index.d.ts
CHANGED
package/esm/index.js
CHANGED
package/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA","sourcesContent":["export * from './client.js'\nexport * from './storage.js'\nexport * from './stub.js'\nexport * from './transport.js'\nexport * from './types.js'\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,mBAAmB,CAAA;AACjC,cAAc,WAAW,CAAA;AACzB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA","sourcesContent":["export * from './client.js'\nexport * from './crypto.js'\nexport * from './storage.js'\nexport * from './storage-test.js'\nexport * from './stub.js'\nexport * from './transport.js'\nexport * from './types.js'\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ITelegramStorage, MaybeAsync } from '@mtcute/core';
|
|
2
|
+
import { Logger, TlReaderMap, TlWriterMap } from '@mtcute/core/utils.js';
|
|
3
|
+
export declare const stubPeerUser: ITelegramStorage.PeerInfo;
|
|
4
|
+
export declare function testStorage<T extends ITelegramStorage>(s: T, params?: {
|
|
5
|
+
skipEntityOverwrite?: boolean;
|
|
6
|
+
customTests?: (s: T) => void;
|
|
7
|
+
}): void;
|
|
8
|
+
interface IStateStorage {
|
|
9
|
+
setup?(log: Logger, readerMap: TlReaderMap, writerMap: TlWriterMap): void;
|
|
10
|
+
load?(): MaybeAsync<void>;
|
|
11
|
+
save?(): MaybeAsync<void>;
|
|
12
|
+
destroy?(): MaybeAsync<void>;
|
|
13
|
+
reset(): MaybeAsync<void>;
|
|
14
|
+
getState(key: string): MaybeAsync<unknown>;
|
|
15
|
+
setState(key: string, state: unknown, ttl?: number): MaybeAsync<void>;
|
|
16
|
+
deleteState(key: string): MaybeAsync<void>;
|
|
17
|
+
getCurrentScene(key: string): MaybeAsync<string | null>;
|
|
18
|
+
setCurrentScene(key: string, scene: string, ttl?: number): MaybeAsync<void>;
|
|
19
|
+
deleteCurrentScene(key: string): MaybeAsync<void>;
|
|
20
|
+
getRateLimit(key: string, limit: number, window: number): MaybeAsync<[number, number]>;
|
|
21
|
+
resetRateLimit(key: string): MaybeAsync<void>;
|
|
22
|
+
}
|
|
23
|
+
export declare function testStateStorage(s: IStateStorage): void;
|
|
24
|
+
export {};
|