@armatofik/tgsnake-core 1.0.0

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.
Files changed (171) hide show
  1. package/COPYING +674 -0
  2. package/COPYING.lesser +165 -0
  3. package/README.md +88 -0
  4. package/lib/package.json +46 -0
  5. package/lib/src/Logger.d.ts +3 -0
  6. package/lib/src/Logger.js +9 -0
  7. package/lib/src/Queue.d.ts +19 -0
  8. package/lib/src/Queue.js +52 -0
  9. package/lib/src/Timeout.d.ts +9 -0
  10. package/lib/src/Timeout.js +44 -0
  11. package/lib/src/Version.node.d.ts +4 -0
  12. package/lib/src/Version.node.js +26 -0
  13. package/lib/src/client/Auth.d.ts +40 -0
  14. package/lib/src/client/Auth.js +317 -0
  15. package/lib/src/client/Client.d.ts +83 -0
  16. package/lib/src/client/Client.js +461 -0
  17. package/lib/src/client/Session.d.ts +9 -0
  18. package/lib/src/client/Session.js +132 -0
  19. package/lib/src/client/index.d.ts +3 -0
  20. package/lib/src/client/index.js +39 -0
  21. package/lib/src/connection/TCP/TCPAbridged.d.ts +9 -0
  22. package/lib/src/connection/TCP/TCPAbridged.js +47 -0
  23. package/lib/src/connection/TCP/TCPAbridgedO.d.ts +12 -0
  24. package/lib/src/connection/TCP/TCPAbridgedO.js +140 -0
  25. package/lib/src/connection/TCP/TCPFull.d.ts +10 -0
  26. package/lib/src/connection/TCP/TCPFull.js +43 -0
  27. package/lib/src/connection/TCP/TCPIntermediate.d.ts +9 -0
  28. package/lib/src/connection/TCP/TCPIntermediate.js +31 -0
  29. package/lib/src/connection/TCP/TCPIntermediateO.d.ts +12 -0
  30. package/lib/src/connection/TCP/TCPIntermediateO.js +123 -0
  31. package/lib/src/connection/TCP/TCPPaddedIntermediate.d.ts +9 -0
  32. package/lib/src/connection/TCP/TCPPaddedIntermediate.js +38 -0
  33. package/lib/src/connection/TCP/index.d.ts +7 -0
  34. package/lib/src/connection/TCP/index.js +17 -0
  35. package/lib/src/connection/TCP/tcp.d.ts +17 -0
  36. package/lib/src/connection/TCP/tcp.js +98 -0
  37. package/lib/src/connection/WebSocket.d.ts +21 -0
  38. package/lib/src/connection/WebSocket.js +279 -0
  39. package/lib/src/connection/connection.d.ts +53 -0
  40. package/lib/src/connection/connection.js +189 -0
  41. package/lib/src/connection/index.d.ts +4 -0
  42. package/lib/src/connection/index.js +41 -0
  43. package/lib/src/crypto/Aes.d.ts +10 -0
  44. package/lib/src/crypto/Aes.js +135 -0
  45. package/lib/src/crypto/Mtproto.d.ts +5 -0
  46. package/lib/src/crypto/Mtproto.js +123 -0
  47. package/lib/src/crypto/Password.d.ts +5 -0
  48. package/lib/src/crypto/Password.js +92 -0
  49. package/lib/src/crypto/Prime.d.ts +4 -0
  50. package/lib/src/crypto/Prime.js +64 -0
  51. package/lib/src/crypto/RSA.d.ts +7 -0
  52. package/lib/src/crypto/RSA.js +99 -0
  53. package/lib/src/crypto/SecretChat.d.ts +5 -0
  54. package/lib/src/crypto/SecretChat.js +136 -0
  55. package/lib/src/crypto/index.d.ts +6 -0
  56. package/lib/src/crypto/index.js +42 -0
  57. package/lib/src/errors/Base.d.ts +9 -0
  58. package/lib/src/errors/Base.js +50 -0
  59. package/lib/src/errors/Client.d.ts +21 -0
  60. package/lib/src/errors/Client.js +29 -0
  61. package/lib/src/errors/File.d.ts +13 -0
  62. package/lib/src/errors/File.js +30 -0
  63. package/lib/src/errors/RpcError.d.ts +22 -0
  64. package/lib/src/errors/RpcError.js +120 -0
  65. package/lib/src/errors/SecretChat.d.ts +13 -0
  66. package/lib/src/errors/SecretChat.js +30 -0
  67. package/lib/src/errors/WebSocket.d.ts +13 -0
  68. package/lib/src/errors/WebSocket.js +30 -0
  69. package/lib/src/errors/exceptions/All.d.ts +774 -0
  70. package/lib/src/errors/exceptions/All.js +778 -0
  71. package/lib/src/errors/exceptions/BadRequest400.d.ts +2345 -0
  72. package/lib/src/errors/exceptions/BadRequest400.js +2945 -0
  73. package/lib/src/errors/exceptions/Flood420.d.ts +37 -0
  74. package/lib/src/errors/exceptions/Flood420.js +49 -0
  75. package/lib/src/errors/exceptions/Forbidden403.d.ts +205 -0
  76. package/lib/src/errors/exceptions/Forbidden403.js +260 -0
  77. package/lib/src/errors/exceptions/InternalServerError500.d.ts +221 -0
  78. package/lib/src/errors/exceptions/InternalServerError500.js +280 -0
  79. package/lib/src/errors/exceptions/NotAcceptable406.d.ts +117 -0
  80. package/lib/src/errors/exceptions/NotAcceptable406.js +149 -0
  81. package/lib/src/errors/exceptions/NotFound404.d.ts +9 -0
  82. package/lib/src/errors/exceptions/NotFound404.js +14 -0
  83. package/lib/src/errors/exceptions/SeeOther303.d.ts +25 -0
  84. package/lib/src/errors/exceptions/SeeOther303.js +34 -0
  85. package/lib/src/errors/exceptions/ServiceUnavailable503.d.ts +17 -0
  86. package/lib/src/errors/exceptions/ServiceUnavailable503.js +24 -0
  87. package/lib/src/errors/exceptions/Unauthorized401.d.ts +41 -0
  88. package/lib/src/errors/exceptions/Unauthorized401.js +54 -0
  89. package/lib/src/errors/exceptions/index.d.ts +10 -0
  90. package/lib/src/errors/exceptions/index.js +48 -0
  91. package/lib/src/errors/index.d.ts +31 -0
  92. package/lib/src/errors/index.js +111 -0
  93. package/lib/src/file/Download.d.ts +11 -0
  94. package/lib/src/file/Download.js +118 -0
  95. package/lib/src/file/File.d.ts +20 -0
  96. package/lib/src/file/File.js +82 -0
  97. package/lib/src/file/Upload.d.ts +19 -0
  98. package/lib/src/file/Upload.js +250 -0
  99. package/lib/src/file/index.d.ts +3 -0
  100. package/lib/src/file/index.js +11 -0
  101. package/lib/src/helpers.d.ts +34 -0
  102. package/lib/src/helpers.js +358 -0
  103. package/lib/src/index.d.ts +16 -0
  104. package/lib/src/index.js +56 -0
  105. package/lib/src/platform.node.d.ts +36 -0
  106. package/lib/src/platform.node.js +109 -0
  107. package/lib/src/raw/All.d.ts +2400 -0
  108. package/lib/src/raw/All.js +2403 -0
  109. package/lib/src/raw/Raw.d.ts +29195 -0
  110. package/lib/src/raw/Raw.js +97277 -0
  111. package/lib/src/raw/core/BytesIO.d.ts +33 -0
  112. package/lib/src/raw/core/BytesIO.js +145 -0
  113. package/lib/src/raw/core/GzipPacked.d.ts +10 -0
  114. package/lib/src/raw/core/GzipPacked.js +60 -0
  115. package/lib/src/raw/core/Message.d.ts +13 -0
  116. package/lib/src/raw/core/Message.js +81 -0
  117. package/lib/src/raw/core/MsgContainer.d.ts +11 -0
  118. package/lib/src/raw/core/MsgContainer.js +69 -0
  119. package/lib/src/raw/core/TLObject.d.ts +19 -0
  120. package/lib/src/raw/core/TLObject.js +108 -0
  121. package/lib/src/raw/core/UpdateSecretChat.d.ts +40 -0
  122. package/lib/src/raw/core/UpdateSecretChat.js +88 -0
  123. package/lib/src/raw/core/index.d.ts +8 -0
  124. package/lib/src/raw/core/index.js +52 -0
  125. package/lib/src/raw/core/primitive/Bool.d.ts +20 -0
  126. package/lib/src/raw/core/primitive/Bool.js +41 -0
  127. package/lib/src/raw/core/primitive/Bytes.d.ts +7 -0
  128. package/lib/src/raw/core/primitive/Bytes.js +41 -0
  129. package/lib/src/raw/core/primitive/Double.d.ts +7 -0
  130. package/lib/src/raw/core/primitive/Double.js +24 -0
  131. package/lib/src/raw/core/primitive/Float.d.ts +7 -0
  132. package/lib/src/raw/core/primitive/Float.js +24 -0
  133. package/lib/src/raw/core/primitive/Int.d.ts +23 -0
  134. package/lib/src/raw/core/primitive/Int.js +122 -0
  135. package/lib/src/raw/core/primitive/String.d.ts +7 -0
  136. package/lib/src/raw/core/primitive/String.js +15 -0
  137. package/lib/src/raw/core/primitive/Vector.d.ts +9 -0
  138. package/lib/src/raw/core/primitive/Vector.js +50 -0
  139. package/lib/src/raw/core/primitive/index.d.ts +7 -0
  140. package/lib/src/raw/core/primitive/index.js +22 -0
  141. package/lib/src/raw/index.d.ts +3 -0
  142. package/lib/src/raw/index.js +17 -0
  143. package/lib/src/session/Auth.d.ts +15 -0
  144. package/lib/src/session/Auth.js +254 -0
  145. package/lib/src/session/Session.d.ts +58 -0
  146. package/lib/src/session/Session.js +571 -0
  147. package/lib/src/session/index.d.ts +7 -0
  148. package/lib/src/session/index.js +49 -0
  149. package/lib/src/session/internals/DataCenter.d.ts +42 -0
  150. package/lib/src/session/internals/DataCenter.js +80 -0
  151. package/lib/src/session/internals/MsgFactory.d.ts +3 -0
  152. package/lib/src/session/internals/MsgFactory.js +23 -0
  153. package/lib/src/session/internals/MsgId.d.ts +9 -0
  154. package/lib/src/session/internals/MsgId.js +24 -0
  155. package/lib/src/session/internals/SeqNo.d.ts +6 -0
  156. package/lib/src/session/internals/SeqNo.js +18 -0
  157. package/lib/src/session/secretChats/SecretChat.d.ts +29 -0
  158. package/lib/src/session/secretChats/SecretChat.js +527 -0
  159. package/lib/src/session/secretChats/index.d.ts +1 -0
  160. package/lib/src/session/secretChats/index.js +5 -0
  161. package/lib/src/storage/Abstract.d.ts +68 -0
  162. package/lib/src/storage/Abstract.js +6 -0
  163. package/lib/src/storage/SecretChat.d.ts +42 -0
  164. package/lib/src/storage/SecretChat.js +99 -0
  165. package/lib/src/storage/Session.d.ts +63 -0
  166. package/lib/src/storage/Session.js +245 -0
  167. package/lib/src/storage/StringSession.d.ts +4 -0
  168. package/lib/src/storage/StringSession.js +77 -0
  169. package/lib/src/storage/index.d.ts +4 -0
  170. package/lib/src/storage/index.js +12 -0
  171. package/package.json +46 -0
@@ -0,0 +1,527 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SecretChat = void 0;
4
+ const index_js_1 = require("../../raw/index.js");
5
+ const index_js_2 = require("../../storage/index.js");
6
+ const platform_node_js_1 = require("../../platform.node.js");
7
+ const Logger_js_1 = require("../../Logger.js");
8
+ const index_js_3 = require("../../errors/index.js");
9
+ const index_js_4 = require("../../crypto/index.js");
10
+ const helpers_js_1 = require("../../helpers.js");
11
+ function sha1(data) {
12
+ const hash = platform_node_js_1.crypto.createHash('sha1');
13
+ hash.update(data);
14
+ return hash.digest();
15
+ }
16
+ class SecretChat {
17
+ _storage;
18
+ _client;
19
+ _dhConfig;
20
+ _mutex;
21
+ _tempAuthKey;
22
+ _waiting;
23
+ constructor(storage, client) {
24
+ this._storage = storage;
25
+ this._client = client;
26
+ this._mutex = new platform_node_js_1.Mutex();
27
+ this._tempAuthKey = new Map();
28
+ this._waiting = [];
29
+ }
30
+ async reqDHConfig() {
31
+ const release = await this._mutex.acquire();
32
+ try {
33
+ let version = 0;
34
+ if (this._dhConfig) {
35
+ if (this._dhConfig instanceof index_js_1.Raw.messages.DhConfig) {
36
+ version = this._dhConfig.version;
37
+ }
38
+ }
39
+ const dh = await this._client.invoke(new index_js_1.Raw.messages.GetDhConfig({
40
+ randomLength: 0,
41
+ version: version,
42
+ }));
43
+ if (dh instanceof index_js_1.Raw.messages.DhConfigNotModified) {
44
+ return this._dhConfig;
45
+ }
46
+ this._dhConfig = dh;
47
+ return dh;
48
+ }
49
+ finally {
50
+ release();
51
+ }
52
+ }
53
+ async start(userId) {
54
+ Logger_js_1.Logger.debug(`[127] starting secret chat for ${userId}`);
55
+ const peer = await this._client.resolvePeer(userId);
56
+ const dh = await this.reqDHConfig();
57
+ const p = await (0, helpers_js_1.bufferToBigint)(dh.p, false);
58
+ const a = await (0, helpers_js_1.bufferToBigint)(platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(256)), false);
59
+ const gA = (0, helpers_js_1.bigIntPow)(BigInt(dh.g), a, p);
60
+ index_js_3.SecurityCheckMismatch.check(BigInt(1) < gA && gA < p - BigInt(1), 'gA must be greater than one and smaller than p-1');
61
+ index_js_3.SecurityCheckMismatch.check(BigInt(2) ** BigInt(2048 - 64) < gA && gA < p - BigInt(2) ** BigInt(2048 - 64), 'gA must be greater than 2^{2048 - 64} and smaller than p-2^{2048 -64}');
62
+ Logger_js_1.Logger.debug('[111] gA validation: OK');
63
+ const res = await this._client.invoke(new index_js_1.Raw.messages.RequestEncryption({
64
+ userId: peer,
65
+ gA: await (0, helpers_js_1.bigintToBuffer)(gA, 256, false),
66
+ randomId: platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(4)).readInt32LE(),
67
+ }));
68
+ const release = await this._mutex.acquire();
69
+ try {
70
+ await index_js_2.SecretChat.save(this._storage, {
71
+ id: res.id,
72
+ accessHash: BigInt(0),
73
+ authKey: await (0, helpers_js_1.bigintToBuffer)(a, 256, false),
74
+ isAdmin: false,
75
+ });
76
+ }
77
+ finally {
78
+ release();
79
+ }
80
+ this._waiting.push(res.id);
81
+ return res;
82
+ }
83
+ async accept(request) {
84
+ Logger_js_1.Logger.debug(`[125] accepting secret chat from ${request.id}`);
85
+ if (request.id === 0) {
86
+ throw new index_js_3.SecretChatError.AlreadyAccepted();
87
+ }
88
+ const dh = await this.reqDHConfig();
89
+ const p = await (0, helpers_js_1.bufferToBigint)(dh.p, false);
90
+ const b = await (0, helpers_js_1.bufferToBigint)(platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(256)), false);
91
+ const gA = (0, helpers_js_1.bufferToBigint)(request.gA, false);
92
+ const gB = (0, helpers_js_1.bigIntPow)(BigInt(dh.g), b, p);
93
+ const authKey = await (0, helpers_js_1.bigintToBuffer)((0, helpers_js_1.bigIntPow)(gA, b, p), 256, false);
94
+ const fingerprint = sha1(authKey).subarray(-8).readBigInt64LE();
95
+ index_js_3.SecurityCheckMismatch.check(BigInt(1) < gA && gA < p - BigInt(1), 'gA must be greater than one and smaller than p-1');
96
+ index_js_3.SecurityCheckMismatch.check(BigInt(2) ** BigInt(2048 - 64) < gA && gA < p - BigInt(2) ** BigInt(2048 - 64), 'gA must be greater than 2^{2048 - 64} and smaller than p-2^{2048 -64}');
97
+ index_js_3.SecurityCheckMismatch.check(BigInt(1) < gB && gB < p - BigInt(1), 'gB must be greater than one and smaller than p-1');
98
+ index_js_3.SecurityCheckMismatch.check(BigInt(2) ** BigInt(2048 - 64) < gB && gB < p - BigInt(2) ** BigInt(2048 - 64), 'gB must be greater than 2^{2048 - 64} and smaller than p-2^{2048 -64}');
99
+ Logger_js_1.Logger.debug('[126] gA and gB validation: OK');
100
+ const release = await this._mutex.acquire();
101
+ try {
102
+ await index_js_2.SecretChat.save(this._storage, {
103
+ id: request.id,
104
+ accessHash: request.accessHash,
105
+ authKey: authKey,
106
+ isAdmin: false,
107
+ });
108
+ }
109
+ finally {
110
+ release();
111
+ }
112
+ const res = await this._client.invoke(new index_js_1.Raw.messages.AcceptEncryption({
113
+ peer: new index_js_1.Raw.InputEncryptedChat({
114
+ chatId: request.id,
115
+ accessHash: request.accessHash,
116
+ }),
117
+ gB: await (0, helpers_js_1.bigintToBuffer)(gB, 256, false),
118
+ keyFingerprint: fingerprint,
119
+ }));
120
+ await this.notifyLayer(request.id);
121
+ return res;
122
+ }
123
+ async finish(chat) {
124
+ Logger_js_1.Logger.debug(`[129] finishing creating secret chat ${chat.id}`);
125
+ const dh = await this.reqDHConfig();
126
+ const p = await (0, helpers_js_1.bufferToBigint)(dh.p, false);
127
+ const gAOrB = await (0, helpers_js_1.bufferToBigint)(chat.gAOrB, false);
128
+ index_js_3.SecurityCheckMismatch.check(BigInt(1) < gAOrB && gAOrB < p - BigInt(1), 'gAOrB must be greater than one and smaller than p-1');
129
+ index_js_3.SecurityCheckMismatch.check(BigInt(2) ** BigInt(2048 - 64) < gAOrB && gAOrB < p - BigInt(2) ** BigInt(2048 - 64), 'gAOrB must be greater than 2^{2048 - 64} and smaller than p-2^{2048 -64}');
130
+ Logger_js_1.Logger.debug('[128] gAOrB validation: OK');
131
+ const peer = await this._storage.getSecretChatById(chat.id);
132
+ if (!peer) {
133
+ throw new index_js_3.SecretChatError.ChatNotFound(chat.id);
134
+ }
135
+ const a = await (0, helpers_js_1.bufferToBigint)(peer.authKey, false);
136
+ const authKey = await (0, helpers_js_1.bigintToBuffer)((0, helpers_js_1.bigIntPow)(gAOrB, a, p), 256, false);
137
+ const fingerprint = sha1(authKey).subarray(-8).readBigInt64LE();
138
+ if (fingerprint !== chat.keyFingerprint) {
139
+ throw new index_js_3.SecretChatError.FingerprintMismatch();
140
+ }
141
+ const release = await this._mutex.acquire();
142
+ try {
143
+ await this._storage.removeSecretChatById(peer.id);
144
+ await index_js_2.SecretChat.save(this._storage, {
145
+ id: chat.id,
146
+ accessHash: chat.accessHash,
147
+ authKey: authKey,
148
+ isAdmin: true,
149
+ });
150
+ }
151
+ finally {
152
+ release();
153
+ }
154
+ const index = this._waiting.findIndex((id) => id === chat.id);
155
+ if (index >= 0) {
156
+ this._waiting.splice(index, 1);
157
+ }
158
+ return this.notifyLayer(chat.id);
159
+ }
160
+ async notifyLayer(chatId) {
161
+ Logger_js_1.Logger.debug(`[130] notify layer for ${chatId}`);
162
+ const peer = await this._storage.getSecretChatById(chatId);
163
+ if (!peer) {
164
+ throw new index_js_3.SecretChatError.ChatNotFound(chatId);
165
+ }
166
+ if (peer.layer !== 8) {
167
+ return this._client.invoke(new index_js_1.Raw.messages.SendEncryptedService({
168
+ peer: peer.input,
169
+ randomId: platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(8)).readBigInt64LE(),
170
+ data: await this.encrypt(chatId, new index_js_1.Raw.DecryptedMessageService8({
171
+ randomId: platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(8)).readBigInt64LE(),
172
+ randomBytes: platform_node_js_1.crypto.randomBytes(15 + 4 * Math.floor(Math.random() * 2)),
173
+ action: new index_js_1.Raw.DecryptedMessageActionNotifyLayer17({
174
+ layer: Math.min(peer.layer, index_js_1.Raw.Layer),
175
+ }),
176
+ })),
177
+ }));
178
+ }
179
+ return;
180
+ }
181
+ async destroy(chatId) {
182
+ Logger_js_1.Logger.debug(`[131] destroying secret chat ${chatId}`);
183
+ const release = await this._mutex.acquire();
184
+ try {
185
+ await this._storage.removeSecretChatById(chatId);
186
+ }
187
+ finally {
188
+ release();
189
+ }
190
+ Logger_js_1.Logger.debug(`[132] ${chatId} was removed from session`);
191
+ try {
192
+ await this._client.invoke(new index_js_1.Raw.messages.DiscardEncryption({
193
+ chatId: chatId,
194
+ }));
195
+ }
196
+ catch (_error) {
197
+ }
198
+ Logger_js_1.Logger.debug(`[133] ${chatId} already destroyed`);
199
+ return true;
200
+ }
201
+ async rekeying(chatId) {
202
+ Logger_js_1.Logger.debug(`[114] re-keying ${chatId}: initiator`);
203
+ const peer = await this._storage.getSecretChatById(chatId);
204
+ if (!peer) {
205
+ throw new index_js_3.SecretChatError.ChatNotFound(chatId);
206
+ }
207
+ const dh = await this.reqDHConfig();
208
+ const p = await (0, helpers_js_1.bufferToBigint)(dh.p, false);
209
+ const a = await (0, helpers_js_1.bufferToBigint)(platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(256)), false);
210
+ const gA = (0, helpers_js_1.bigIntPow)(BigInt(dh.g), a, p);
211
+ let e = platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(64)).readBigInt64LE();
212
+ peer.rekeyStep = 1;
213
+ peer.rekeyExchange = e;
214
+ index_js_3.SecurityCheckMismatch.check(BigInt(1) < gA && gA < p - BigInt(1), 'gA must be greater than one and smaller than p-1');
215
+ index_js_3.SecurityCheckMismatch.check(BigInt(2) ** BigInt(2048 - 64) < gA && gA < p - BigInt(2) ** BigInt(2048 - 64), 'gA must be greater than 2^{2048 - 64} and smaller than p-2^{2048 -64}');
216
+ Logger_js_1.Logger.debug('[115] gA validation: OK');
217
+ const release = await this._mutex.acquire();
218
+ try {
219
+ await peer.update(this._storage);
220
+ this._tempAuthKey.set(e, await (0, helpers_js_1.bigintToBuffer)(a, 256, false));
221
+ }
222
+ finally {
223
+ release();
224
+ }
225
+ return this._client.invoke(new index_js_1.Raw.messages.SendEncryptedService({
226
+ peer: peer.input,
227
+ randomId: platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(8)).readBigInt64LE(),
228
+ data: await this.encrypt(chatId, new index_js_1.Raw.DecryptedMessageService17({
229
+ randomId: platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(8)).readBigInt64LE(),
230
+ action: new index_js_1.Raw.DecryptedMessageActionRequestKey20({
231
+ gA: await (0, helpers_js_1.bigintToBuffer)(gA, 256, false),
232
+ exchangeId: e,
233
+ }),
234
+ })),
235
+ }));
236
+ }
237
+ async acceptRekeying(chatId, action) {
238
+ Logger_js_1.Logger.debug(`[116] re-keying ${chatId}: accepting`);
239
+ const peer = await this._storage.getSecretChatById(chatId);
240
+ if (!peer) {
241
+ throw new index_js_3.SecretChatError.ChatNotFound(chatId);
242
+ }
243
+ if (peer.rekeyStep) {
244
+ if (peer.rekeyExchange > action.exchangeId) {
245
+ Logger_js_1.Logger.info(`[117] Aborting rekeying: received exchangeId smaller than our exchangeId`);
246
+ return;
247
+ }
248
+ if (peer.rekeyExchange === action.exchangeId) {
249
+ Logger_js_1.Logger.info(`[118] Aborting rekeying: received exchangeId equal with our exchangeId`);
250
+ const release = await this._mutex.acquire();
251
+ try {
252
+ peer.rekeyStep = 0;
253
+ peer.rekeyExchange = BigInt(0);
254
+ await peer.update(this._storage);
255
+ }
256
+ finally {
257
+ release();
258
+ }
259
+ return;
260
+ }
261
+ }
262
+ const dh = await this.reqDHConfig();
263
+ const p = await (0, helpers_js_1.bufferToBigint)(dh.p, false);
264
+ const b = await (0, helpers_js_1.bufferToBigint)(platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(256)), false);
265
+ const gA = (0, helpers_js_1.bufferToBigint)(action.gA, false);
266
+ const gB = (0, helpers_js_1.bigIntPow)(BigInt(dh.g), b, p);
267
+ const authKey = await (0, helpers_js_1.bigintToBuffer)((0, helpers_js_1.bigIntPow)(gA, b, p), 256, false);
268
+ const fingerprint = sha1(authKey).subarray(-8);
269
+ index_js_3.SecurityCheckMismatch.check(BigInt(1) < gB && gB < p - BigInt(1), 'gB must be greater than one and smaller than p-1');
270
+ index_js_3.SecurityCheckMismatch.check(BigInt(2) ** BigInt(2048 - 64) < gB && gB < p - BigInt(2) ** BigInt(2048 - 64), 'gB must be greater than 2^{2048 - 64} and smaller than p-2^{2048 -64}');
271
+ Logger_js_1.Logger.debug('[119] gB validation: OK');
272
+ const release = await this._mutex.acquire();
273
+ try {
274
+ this._tempAuthKey.set(action.exchangeId, authKey);
275
+ peer.rekeyStep = 2;
276
+ peer.rekeyExchange = action.exchangeId;
277
+ await peer.update(this._storage);
278
+ }
279
+ finally {
280
+ release();
281
+ }
282
+ return this._client.invoke(new index_js_1.Raw.messages.SendEncryptedService({
283
+ peer: peer.input,
284
+ randomId: platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(8)).readBigInt64LE(),
285
+ data: await this.encrypt(chatId, new index_js_1.Raw.DecryptedMessageService17({
286
+ randomId: platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(8)).readBigInt64LE(),
287
+ action: new index_js_1.Raw.DecryptedMessageActionAcceptKey20({
288
+ gB: await (0, helpers_js_1.bigintToBuffer)(gB, 256, false),
289
+ exchangeId: action.exchangeId,
290
+ keyFingerprint: fingerprint.readBigInt64LE(),
291
+ }),
292
+ })),
293
+ }));
294
+ }
295
+ async commitRekeying(chatId, action) {
296
+ Logger_js_1.Logger.debug(`[120] re-keying ${chatId}: commiting`);
297
+ const peer = await this._storage.getSecretChatById(chatId);
298
+ if (!peer) {
299
+ throw new index_js_3.SecretChatError.ChatNotFound(chatId);
300
+ }
301
+ if (peer.rekeyStep !== 1 || !this._tempAuthKey.has(action.exchangeId)) {
302
+ const release = await this._mutex.acquire();
303
+ try {
304
+ peer.rekeyStep = 0;
305
+ peer.rekeyExchange = BigInt(0);
306
+ await peer.update(this._storage);
307
+ }
308
+ finally {
309
+ release();
310
+ }
311
+ return;
312
+ }
313
+ const dh = await this.reqDHConfig();
314
+ const p = await (0, helpers_js_1.bufferToBigint)(dh.p, false);
315
+ const gB = await (0, helpers_js_1.bufferToBigint)(action.gB, false);
316
+ const authKey = await (0, helpers_js_1.bigintToBuffer)((0, helpers_js_1.bigIntPow)(gB, await (0, helpers_js_1.bufferToBigint)(this._tempAuthKey.get(action.exchangeId)), p), 256, false);
317
+ const fingerprint = sha1(authKey).subarray(-8).readBigInt64LE();
318
+ index_js_3.SecurityCheckMismatch.check(BigInt(1) < gB && gB < p - BigInt(1), 'gB must be greater than one and smaller than p-1');
319
+ index_js_3.SecurityCheckMismatch.check(BigInt(2) ** BigInt(2048 - 64) < gB && gB < p - BigInt(2) ** BigInt(2048 - 64), 'gB must be greater than 2^{2048 - 64} and smaller than p-2^{2048 -64}');
320
+ Logger_js_1.Logger.debug('[121] gB validation: OK');
321
+ if (fingerprint !== action.keyFingerprint) {
322
+ Logger_js_1.Logger.error(`[122] re-keying ${chatId}: Aborting due mismatched fingerprint`);
323
+ await this._client.invoke(new index_js_1.Raw.messages.SendEncryptedService({
324
+ peer: peer.input,
325
+ randomId: platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(8)).readBigInt64LE(),
326
+ data: await this.encrypt(chatId, new index_js_1.Raw.DecryptedMessageService17({
327
+ randomId: platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(8)).readBigInt64LE(),
328
+ action: new index_js_1.Raw.DecryptedMessageActionAbortKey20({
329
+ exchangeId: action.exchangeId,
330
+ }),
331
+ })),
332
+ }));
333
+ throw new index_js_3.SecretChatError.FingerprintMismatch();
334
+ }
335
+ const response = await this._client.invoke(new index_js_1.Raw.messages.SendEncryptedService({
336
+ peer: peer.input,
337
+ randomId: platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(8)).readBigInt64LE(),
338
+ data: await this.encrypt(chatId, new index_js_1.Raw.DecryptedMessageService17({
339
+ randomId: platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(8)).readBigInt64LE(),
340
+ action: new index_js_1.Raw.DecryptedMessageActionCommitKey20({
341
+ exchangeId: action.exchangeId,
342
+ keyFingerprint: action.keyFingerprint,
343
+ }),
344
+ })),
345
+ }));
346
+ const release = await this._mutex.acquire();
347
+ try {
348
+ this._tempAuthKey.delete(action.exchangeId);
349
+ peer.rekeyStep = 0;
350
+ peer.rekeyExchange = BigInt(0);
351
+ peer.authKey = authKey;
352
+ peer.timeRekey = 100;
353
+ peer.changed = Date.now() / 1000;
354
+ await peer.update(this._storage);
355
+ }
356
+ finally {
357
+ release();
358
+ }
359
+ return response;
360
+ }
361
+ async finalRekeying(chatId, action) {
362
+ Logger_js_1.Logger.debug(`[123] re-keying ${chatId}: finishing`);
363
+ const peer = await this._storage.getSecretChatById(chatId);
364
+ if (!peer) {
365
+ throw new index_js_3.SecretChatError.ChatNotFound(chatId);
366
+ }
367
+ if (peer.rekeyStep !== 2 || !this._tempAuthKey.has(action.exchangeId)) {
368
+ return;
369
+ }
370
+ const fingerprint = sha1(this._tempAuthKey.get(action.exchangeId))
371
+ .subarray(-8)
372
+ .readBigInt64LE();
373
+ if (fingerprint !== action.keyFingerprint) {
374
+ Logger_js_1.Logger.error(`[124] re-keying ${chatId}: Aborting due mismatched fingerprint`);
375
+ await this._client.invoke(new index_js_1.Raw.messages.SendEncryptedService({
376
+ peer: peer.input,
377
+ randomId: platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(8)).readBigInt64LE(),
378
+ data: await this.encrypt(chatId, new index_js_1.Raw.DecryptedMessageService17({
379
+ randomId: platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(8)).readBigInt64LE(),
380
+ action: new index_js_1.Raw.DecryptedMessageActionAbortKey20({
381
+ exchangeId: action.exchangeId,
382
+ }),
383
+ })),
384
+ }));
385
+ throw new index_js_3.SecretChatError.FingerprintMismatch();
386
+ }
387
+ const release = await this._mutex.acquire();
388
+ try {
389
+ peer.rekeyStep = 0;
390
+ peer.rekeyExchange = BigInt(0);
391
+ peer.authKey = this._tempAuthKey.get(action.exchangeId);
392
+ peer.timeRekey = 100;
393
+ peer.changed = Date.now() / 1000;
394
+ this._tempAuthKey.delete(action.exchangeId);
395
+ await peer.update(this._storage);
396
+ }
397
+ finally {
398
+ release();
399
+ }
400
+ return this._client.invoke(new index_js_1.Raw.messages.SendEncryptedService({
401
+ peer: peer.input,
402
+ randomId: platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(8)).readBigInt64LE(),
403
+ data: await this.encrypt(chatId, new index_js_1.Raw.DecryptedMessageService17({
404
+ randomId: platform_node_js_1.Buffer.from(platform_node_js_1.crypto.randomBytes(8)).readBigInt64LE(),
405
+ action: new index_js_1.Raw.DecryptedMessageActionNoop20(),
406
+ })),
407
+ }));
408
+ }
409
+ async decrypt(message) {
410
+ let decrypted;
411
+ if (!this._waiting.includes(message.chatId)) {
412
+ const peer = await this._storage.getSecretChatById(message.chatId);
413
+ if (!peer) {
414
+ throw new index_js_3.SecretChatError.ChatNotFound(message.chatId);
415
+ }
416
+ if (peer.mtproto === 2) {
417
+ try {
418
+ decrypted = await index_js_4.SecretChats.unpack(message, peer.authKey, peer.isAdmin, peer.mtproto);
419
+ }
420
+ catch (error) {
421
+ if (error instanceof index_js_3.SecretChatError.FingerprintMismatch) {
422
+ await this.destroy(message.chatId);
423
+ throw error;
424
+ }
425
+ decrypted = await index_js_4.SecretChats.unpack(message, peer.authKey, peer.isAdmin, 1);
426
+ peer.mtproto = 1;
427
+ Logger_js_1.Logger.debug(`[112] Switch MTProto version for ${message.chatId} to ${peer.mtproto}`);
428
+ }
429
+ }
430
+ else {
431
+ try {
432
+ decrypted = await index_js_4.SecretChats.unpack(message, peer.authKey, peer.isAdmin, peer.mtproto);
433
+ }
434
+ catch (error) {
435
+ if (error instanceof index_js_3.SecretChatError.FingerprintMismatch) {
436
+ await this.destroy(message.chatId);
437
+ throw error;
438
+ }
439
+ decrypted = await index_js_4.SecretChats.unpack(message, peer.authKey, peer.isAdmin, 2);
440
+ peer.mtproto = 2;
441
+ Logger_js_1.Logger.debug(`[113] Switch MTProto version for ${message.chatId} to ${peer.mtproto}`);
442
+ }
443
+ }
444
+ const release = await this._mutex.acquire();
445
+ try {
446
+ peer.timeRekey -= 1;
447
+ await peer.update(this._storage);
448
+ }
449
+ finally {
450
+ release();
451
+ }
452
+ if ((peer.timeRekey <= 0 || Date.now() / 1000 - peer.changed < 7 * 24 * 60 * 60) &&
453
+ peer.rekeyStep === 0) {
454
+ await this.rekeying(message.chatId);
455
+ }
456
+ }
457
+ return decrypted;
458
+ }
459
+ async encrypt(chatId, message) {
460
+ const peer = await this._storage.getSecretChatById(chatId);
461
+ if (!peer) {
462
+ throw new index_js_3.SecretChatError.ChatNotFound(chatId);
463
+ }
464
+ const release = await this._mutex.acquire();
465
+ const inSeqNo = peer.inSeqNo * 2 + peer.inSeqNoX;
466
+ const outSeqNo = peer.outSeqNo * 2 + peer.outSeqNoX;
467
+ try {
468
+ peer.timeRekey -= 1;
469
+ peer.inSeqNo = inSeqNo;
470
+ peer.outSeqNo = outSeqNo;
471
+ await peer.update(this._storage);
472
+ }
473
+ finally {
474
+ release();
475
+ }
476
+ if (peer.layer > 8) {
477
+ if ((peer.timeRekey <= 0 || Date.now() / 1000 - peer.changed < 7 * 24 * 60 * 60) &&
478
+ peer.rekeyStep === 0) {
479
+ await this.rekeying(chatId);
480
+ }
481
+ }
482
+ return index_js_4.SecretChats.pack(message, peer.authKey, inSeqNo, outSeqNo, peer.isAdmin, peer.layer, peer.mtproto);
483
+ }
484
+ [Symbol.for('nodejs.util.inspect.custom')]() {
485
+ const toPrint = {
486
+ _: this.constructor.name,
487
+ };
488
+ for (const key in this) {
489
+ if (Object.prototype.hasOwnProperty.call(this, key)) {
490
+ const value = this[key];
491
+ if (!key.startsWith('_') && value !== undefined && value !== null) {
492
+ toPrint[key] = value;
493
+ }
494
+ }
495
+ }
496
+ return toPrint;
497
+ }
498
+ [Symbol.for('Deno.customInspect')]() {
499
+ return String((0, platform_node_js_1.inspect)(this[Symbol.for('nodejs.util.inspect.custom')](), { colors: true }));
500
+ }
501
+ toJSON() {
502
+ const toPrint = {
503
+ _: this.constructor.name,
504
+ };
505
+ for (const key in this) {
506
+ if (Object.prototype.hasOwnProperty.call(this, key)) {
507
+ const value = this[key];
508
+ if (!key.startsWith('_') && value !== undefined && value !== null) {
509
+ if (typeof value === 'bigint') {
510
+ toPrint[key] = String(value);
511
+ }
512
+ else if (Array.isArray(value)) {
513
+ toPrint[key] = value.map((v) => (typeof v === 'bigint' ? String(v) : v));
514
+ }
515
+ else {
516
+ toPrint[key] = value;
517
+ }
518
+ }
519
+ }
520
+ }
521
+ return toPrint;
522
+ }
523
+ toString() {
524
+ return `[constructor of ${this.constructor.name}] ${JSON.stringify(this, null, 2)}`;
525
+ }
526
+ }
527
+ exports.SecretChat = SecretChat;
@@ -0,0 +1 @@
1
+ export { SecretChat } from './SecretChat.js';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SecretChat = void 0;
4
+ var SecretChat_js_1 = require("./SecretChat.js");
5
+ Object.defineProperty(exports, "SecretChat", { enumerable: true, get: function () { return SecretChat_js_1.SecretChat; } });
@@ -0,0 +1,68 @@
1
+ import { Raw } from '../raw/index.js';
2
+ import { type SecretChat } from './SecretChat.js';
3
+ import { type Buffer } from '../platform.node.js';
4
+ type MaybePromise<T> = T | Promise<T>;
5
+ export declare abstract class AbstractSession {
6
+ protected abstract _ip: string;
7
+ protected abstract _dcId: number;
8
+ protected abstract _port: number;
9
+ protected abstract _peers: Map<bigint, [
10
+ id: bigint,
11
+ accessHash: bigint,
12
+ type: string,
13
+ username?: Array<string>,
14
+ phoneNumber?: string
15
+ ]>;
16
+ protected abstract _secretChats: Map<number, SecretChat>;
17
+ protected abstract _authKey: Buffer;
18
+ protected abstract _testMode: boolean;
19
+ protected abstract _apiId: number;
20
+ protected abstract _userId: bigint;
21
+ protected abstract _isBot: boolean;
22
+ abstract setAddress(dcId: number, ip: string, port: number, testMode: boolean): MaybePromise<void>;
23
+ abstract setAuthKey(authKey: Buffer, dcId: number): MaybePromise<void>;
24
+ abstract setApiId(apiId: number): MaybePromise<void>;
25
+ abstract setIsBot(isbot: boolean): MaybePromise<void>;
26
+ abstract setUserId(userId: bigint): MaybePromise<void>;
27
+ abstract get authKey(): Buffer;
28
+ abstract get isBot(): boolean;
29
+ abstract get testMode(): boolean;
30
+ abstract get userId(): bigint;
31
+ abstract get apiId(): number;
32
+ abstract get dcId(): number;
33
+ abstract get port(): number;
34
+ abstract get ip(): string;
35
+ abstract get peers(): Map<bigint, [
36
+ id: bigint,
37
+ accessHash: bigint,
38
+ type: string,
39
+ username?: Array<string>,
40
+ phoneNumber?: string
41
+ ]>;
42
+ abstract get secretChats(): Map<number, SecretChat>;
43
+ abstract load(): MaybePromise<void>;
44
+ abstract delete(): MaybePromise<void>;
45
+ abstract save(): MaybePromise<void>;
46
+ abstract move(session: AbstractSession): MaybePromise<void>;
47
+ abstract updatePeers(peers: Array<[
48
+ id: bigint,
49
+ accessHash: bigint,
50
+ type: string,
51
+ username?: Array<string>,
52
+ phoneNumber?: string
53
+ ]>): MaybePromise<void>;
54
+ abstract updateSecretChats(chats: Array<SecretChat>): MaybePromise<void>;
55
+ abstract getSecretChatById(id: number): MaybePromise<SecretChat | undefined>;
56
+ abstract getPeerById(id: bigint): MaybePromise<Raw.InputPeerUser | Raw.InputPeerChat | Raw.InputPeerChannel | undefined>;
57
+ abstract getPeerByUsername(username: string): MaybePromise<Raw.InputPeerUser | Raw.InputPeerChat | Raw.InputPeerChannel | undefined>;
58
+ abstract getPeerByPhoneNumber(phoneNumber: string): MaybePromise<Raw.InputPeerUser | Raw.InputPeerChat | Raw.InputPeerChannel | undefined>;
59
+ abstract removeSecretChatById(id: number): MaybePromise<boolean>;
60
+ abstract updatePts(pts: number, date: number): MaybePromise<void>;
61
+ abstract getPts(): Promise<[pts: number, date: number]>;
62
+ abstract exportString(): string;
63
+ abstract toJSON(): {
64
+ [key: string]: any;
65
+ };
66
+ abstract toString(): string;
67
+ }
68
+ export {};
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AbstractSession = void 0;
4
+ class AbstractSession {
5
+ }
6
+ exports.AbstractSession = AbstractSession;
@@ -0,0 +1,42 @@
1
+ import { Buffer } from '../platform.node.js';
2
+ import { Raw } from '../raw/index.js';
3
+ import { type AbstractSession } from './Abstract.js';
4
+ export declare class SecretChat {
5
+ id: number;
6
+ accessHash: bigint;
7
+ rekeyStep: number;
8
+ rekeyExchange: bigint;
9
+ created: number;
10
+ changed: number;
11
+ isAdmin: boolean;
12
+ authKey: Buffer;
13
+ mtproto: number;
14
+ layer: number;
15
+ inSeqNo: number;
16
+ outSeqNo: number;
17
+ inSeqNoX: number;
18
+ outSeqNoX: number;
19
+ adminId: bigint;
20
+ timeRekey: number;
21
+ ttl: number;
22
+ private _mutex;
23
+ constructor({ id, accessHash, isAdmin, authKey, }: {
24
+ id: number;
25
+ accessHash: bigint;
26
+ isAdmin: boolean;
27
+ authKey: Buffer;
28
+ });
29
+ update(storage: AbstractSession): Promise<boolean>;
30
+ static save(storage: AbstractSession, params: {
31
+ id: number;
32
+ accessHash: bigint;
33
+ isAdmin: boolean;
34
+ authKey: Buffer;
35
+ }): SecretChat;
36
+ static remove(storage: AbstractSession, id: number): Promise<boolean>;
37
+ get input(): Raw.InputEncryptedChat;
38
+ toJSON(): {
39
+ [key: string]: any;
40
+ };
41
+ toString(): string;
42
+ }