kage-baileys 3.0.6 → 3.2.3

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 (216) hide show
  1. package/Example/connection.cjs +4 -0
  2. package/README.MD +4726 -48
  3. package/WAProto/WAProto.proto +3395 -415
  4. package/WAProto/compat.cjs +12 -0
  5. package/WAProto/index.d.ts +47104 -19888
  6. package/WAProto/index.js +131979 -57361
  7. package/lib/Addon/http-error.js +43 -0
  8. package/lib/Addon/index.js +32 -0
  9. package/lib/Addon/keyed-db.js +250 -0
  10. package/lib/Addon/link-preview.js +82 -0
  11. package/lib/Defaults/baileys-version.json +3 -0
  12. package/lib/Defaults/connection.js +110 -0
  13. package/lib/Defaults/constants.js +156 -0
  14. package/lib/Defaults/history.js +46 -0
  15. package/lib/Defaults/index.js +230 -0
  16. package/lib/Defaults/media.js +104 -0
  17. package/lib/Defaults/phonenumber-mcc.json +223 -0
  18. package/lib/Defaults/prefix.js +44 -0
  19. package/lib/Extensions/business-advanced.js +382 -0
  20. package/lib/Extensions/business.js +159 -0
  21. package/lib/Extensions/chats-advanced.js +1106 -0
  22. package/lib/Extensions/chats.js +349 -0
  23. package/lib/Extensions/communities-advanced.js +430 -0
  24. package/lib/Extensions/community.js +94 -0
  25. package/lib/Extensions/groups-advanced.js +343 -0
  26. package/lib/Extensions/index.js +30 -0
  27. package/lib/Extensions/messages-recv-advanced.js +1690 -0
  28. package/lib/Extensions/messages-send-advanced.js +622 -0
  29. package/lib/Extensions/messages-send.js +1380 -0
  30. package/lib/Extensions/newsletter-advanced.js +228 -0
  31. package/lib/Extensions/newsletter.js +72 -0
  32. package/lib/Extensions/socket.js +389 -0
  33. package/lib/Modded/message_builder.js +2084 -4
  34. package/lib/Signal/Group/ciphertext-message.js +54 -0
  35. package/lib/Signal/Group/group-session-builder.js +124 -0
  36. package/lib/Signal/Group/group_cipher.js +216 -0
  37. package/lib/Signal/Group/index.js +124 -0
  38. package/lib/Signal/Group/keyhelper.js +108 -0
  39. package/lib/Signal/Group/sender-chain-key.js +83 -0
  40. package/lib/Signal/Group/sender-key-distribution-message.js +157 -0
  41. package/lib/Signal/Group/sender-key-message.js +166 -0
  42. package/lib/Signal/Group/sender-key-name.js +130 -0
  43. package/lib/Signal/Group/sender-key-record.js +113 -0
  44. package/lib/Signal/Group/sender-key-state.js +208 -0
  45. package/lib/Signal/Group/sender-message-key.js +82 -0
  46. package/lib/Signal/libsignal.js +935 -0
  47. package/lib/Signal/lid-mapping.js +545 -1
  48. package/lib/Socket/Client/index.js +60 -0
  49. package/lib/Socket/Client/types.js +51 -0
  50. package/lib/Socket/Client/websocket.js +152 -0
  51. package/lib/Socket/business.js +831 -0
  52. package/lib/Socket/chats.js +2535 -49
  53. package/lib/Socket/communities.js +450 -1
  54. package/lib/Socket/community.js +1022 -0
  55. package/lib/Socket/dugong.js +1 -1
  56. package/lib/Socket/groups.js +747 -0
  57. package/lib/Socket/index.js +60 -2
  58. package/lib/Socket/messages-recv.js +3450 -5
  59. package/lib/Socket/messages-send.js +3123 -0
  60. package/lib/Socket/mex.js +126 -1
  61. package/lib/Socket/newsletter.js +465 -0
  62. package/lib/Socket/socket.js +2217 -1
  63. package/lib/Store/index.js +79 -0
  64. package/lib/Store/make-cache-manager-store.js +186 -0
  65. package/lib/Store/make-in-memory-store.js +878 -0
  66. package/lib/Store/make-ordered-dictionary.js +187 -0
  67. package/lib/Store/object-repository.js +78 -0
  68. package/lib/Types/Auth.js +25 -0
  69. package/lib/Types/Bussines.js +25 -1
  70. package/lib/Types/Call.js +25 -0
  71. package/lib/Types/Chat.js +39 -0
  72. package/lib/Types/Contact.js +25 -0
  73. package/lib/Types/Events.js +25 -0
  74. package/lib/Types/GroupMetadata.js +25 -0
  75. package/lib/Types/Label.js +76 -0
  76. package/lib/Types/LabelAssociation.js +40 -0
  77. package/lib/Types/Message.js +57 -0
  78. package/lib/Types/Mex.js +56 -1
  79. package/lib/Types/MexUpdates.js +46 -0
  80. package/lib/Types/Newsletter.js +56 -0
  81. package/lib/Types/Product.js +25 -0
  82. package/lib/Types/RichType.js +23 -0
  83. package/lib/Types/Signal.js +25 -0
  84. package/lib/Types/Socket.js +25 -0
  85. package/lib/Types/State.js +92 -0
  86. package/lib/Types/USync.js +25 -0
  87. package/lib/Types/index.js +133 -0
  88. package/lib/Utils/auth-utils.js +703 -0
  89. package/lib/Utils/automation-tools.js +51 -16
  90. package/lib/Utils/baileys-event-stream.js +146 -0
  91. package/lib/Utils/browser-utils.js +95 -0
  92. package/lib/Utils/business.js +525 -0
  93. package/lib/Utils/chat-utils.js +1861 -0
  94. package/lib/Utils/companion-reg-client-utils.js +55 -1
  95. package/lib/Utils/crypto.js +355 -0
  96. package/lib/Utils/decode-wa-message.js +709 -0
  97. package/lib/Utils/event-buffer.js +1323 -8
  98. package/lib/Utils/generics.js +945 -1
  99. package/lib/Utils/history.js +266 -0
  100. package/lib/Utils/identity-change-handler.js +62 -1
  101. package/lib/Utils/index.js +114 -0
  102. package/lib/Utils/link-preview.js +179 -0
  103. package/lib/Utils/logger.js +42 -0
  104. package/lib/Utils/lt-hash.js +73 -0
  105. package/lib/Utils/make-mutex.js +104 -0
  106. package/lib/Utils/message-inspector.js +110 -0
  107. package/lib/Utils/message-retry-manager.js +507 -2
  108. package/lib/Utils/messages-media.js +1931 -1
  109. package/lib/Utils/messages.js +3748 -0
  110. package/lib/Utils/noise-handler.js +423 -0
  111. package/lib/Utils/offline-node-processor.js +53 -1
  112. package/lib/Utils/pre-key-manager.js +255 -1
  113. package/lib/Utils/process-message.js +1592 -0
  114. package/lib/Utils/reporting-utils.js +272 -1
  115. package/lib/Utils/rich-message-utils.js +377 -0
  116. package/lib/Utils/rich-messages.js +1 -1
  117. package/lib/Utils/signal.js +437 -0
  118. package/lib/Utils/stanza-ack.js +51 -1
  119. package/lib/Utils/status-refresh.js +37 -0
  120. package/lib/Utils/status-tools.js +4 -2
  121. package/lib/Utils/sync-action-utils.js +63 -1
  122. package/lib/Utils/tc-token-utils.js +185 -1
  123. package/lib/Utils/terminal-banner.js +31 -0
  124. package/lib/Utils/use-multi-file-auth-state.js +271 -0
  125. package/lib/Utils/use-single-file-auth-state.js +108 -0
  126. package/lib/Utils/use-sqlite-auth-state.js +142 -0
  127. package/lib/Utils/validate-connection.js +497 -1
  128. package/lib/Utils/view-once-compat.js +13 -5
  129. package/lib/VoIP/audio-feeder.js +150 -0
  130. package/lib/VoIP/index.js +289 -0
  131. package/lib/VoIP/relay-transport.js +608 -0
  132. package/lib/VoIP/signaling.js +583 -0
  133. package/lib/VoIP/types.js +30 -0
  134. package/lib/VoIP/wasm-engine.js +1261 -2
  135. package/lib/VoIP/worker-bootstrap.js +1090 -2
  136. package/lib/WABinary/constants.js +2805 -0
  137. package/lib/WABinary/decode.js +649 -2
  138. package/lib/WABinary/encode.js +564 -2
  139. package/lib/WABinary/generic-utils.js +401 -0
  140. package/lib/WABinary/index.js +82 -0
  141. package/lib/WABinary/jid-utils.js +290 -0
  142. package/lib/WABinary/types.js +25 -0
  143. package/lib/WAM/BinaryInfo.js +50 -0
  144. package/lib/WAM/constants.js +45747 -0
  145. package/lib/WAM/encode.js +393 -0
  146. package/lib/WAM/index.js +78 -0
  147. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +135 -0
  148. package/lib/WAUSync/Protocols/USyncContactProtocol.js +110 -0
  149. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +142 -0
  150. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +85 -0
  151. package/lib/WAUSync/Protocols/USyncLIDProtocol.js +69 -0
  152. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +107 -0
  153. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +38 -1
  154. package/lib/WAUSync/Protocols/index.js +83 -0
  155. package/lib/WAUSync/USyncQuery.js +241 -2
  156. package/lib/WAUSync/USyncUser.js +86 -0
  157. package/lib/WAUSync/index.js +78 -0
  158. package/lib/assets/wasm/loader.js +1875 -1
  159. package/lib/assets/wasm/worker-modules.js +11047 -1
  160. package/lib/index.d.ts +126 -0
  161. package/lib/index.js +53 -21
  162. package/lib/index.mjs +437 -0
  163. package/licenses/upstream-MIT.txt +22 -0
  164. package/maintenance/api-coverage.json +1642 -0
  165. package/maintenance/archivos-sha256.json +207 -0
  166. package/maintenance/consumer-validation.log +3 -0
  167. package/maintenance/dependency-audit.json +4 -4
  168. package/maintenance/extension-inventory.json +57 -0
  169. package/maintenance/protocol-update.json +1101 -0
  170. package/maintenance/protocol-wire-audit.json +4 -0
  171. package/maintenance/reference-socket-surface.json +209 -0
  172. package/maintenance/resumen-validacion.json +50 -0
  173. package/maintenance/validation.log +2725 -0
  174. package/maintenance/verification.json +566 -0
  175. package/package.json +107 -9
  176. package/scripts/check-imports.cjs +10 -0
  177. package/scripts/check-package.cjs +40 -0
  178. package/scripts/check-syntax.cjs +1 -1
  179. package/scripts/generate-protobuf.cjs +6 -1
  180. package/scripts/generate-public-types.cjs +9 -0
  181. package/scripts/kage-base64-fix.cjs +45 -0
  182. package/scripts/maintenance.cjs +10 -0
  183. package/test/advanced.test.cjs +24 -0
  184. package/test/base64-fix.test.cjs +49 -0
  185. package/test/maintenance.test.cjs +1 -1
  186. package/test/npm-publication.test.cjs +141 -0
  187. package/test/recepcion-reparada.test.cjs +98 -0
  188. package/test/resilience-binary.test.cjs +69 -0
  189. package/test/resilience-transport.test.cjs +34 -0
  190. package/test/types.test.ts +5 -0
  191. package/test/upgrade.test.cjs +104 -0
  192. package/tsconfig.json +20 -0
  193. package/WAProto/p.html +0 -1
  194. package/lib/KageExtra/Modded/message_builder.js +0 -2330
  195. package/lib/KageExtra/VoIP/audio-feeder.js +0 -136
  196. package/lib/KageExtra/VoIP/index.js +0 -282
  197. package/lib/KageExtra/VoIP/relay-transport.js +0 -559
  198. package/lib/KageExtra/VoIP/signaling.js +0 -603
  199. package/lib/KageExtra/VoIP/types.js +0 -17
  200. package/lib/KageExtra/VoIP/wasm-engine.js +0 -1214
  201. package/lib/KageExtra/VoIP/worker-bootstrap.js +0 -1042
  202. package/lib/KageExtra/assets/wasm/loader.js +0 -5
  203. package/lib/KageExtra/assets/wasm/whatsapp.wasm +0 -0
  204. package/lib/KageExtra/assets/wasm/worker-modules.js +0 -273
  205. package/lib/KageExtra/index.js +0 -3
  206. package/lib/KageExtra/package.json +0 -1
  207. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +0 -53
  208. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +0 -24
  209. package/maintenance/revision-full-check.txt +0 -1097
  210. package/maintenance/revision-library-tests.tap +0 -1088
  211. package/maintenance/revision-protobuf.txt +0 -5
  212. package/maintenance/revision-syntax.txt +0 -5
  213. package/maintenance/schema-coverage.json +0 -23
  214. package/maintenance/schema-merge.json +0 -30
  215. package/maintenance/validation-node20.txt +0 -191
  216. package/maintenance/validation-node22.txt +0 -237
@@ -130,9 +130,12 @@ const makeNoiseHandler = ({ keyPair: { private: privateKey, public: publicKey },
130
130
  return (inBytes.readUInt8() << 16) | inBytes.readUInt16BE(1);
131
131
  }
132
132
  };
133
+ if (!Buffer.isBuffer(newData) && !(newData instanceof Uint8Array)) throw new Error('NOISE_INVALID_CHUNK');
134
+ if (inBytes.length + newData.byteLength > 32 * 1024 * 1024) { inBytes = Buffer.alloc(0); throw new Error('NOISE_BUFFER_LIMIT'); }
133
135
  inBytes = Buffer.concat([inBytes, newData]);
134
136
  logger.trace(`recv ${newData.length} bytes, total recv ${inBytes.length} bytes`);
135
137
  let size = getBytesSize();
138
+ if (size === 0) { inBytes = Buffer.alloc(0); throw new Error('NOISE_EMPTY_FRAME'); }
136
139
  while (size && inBytes.length >= size + 3) {
137
140
  let frame = inBytes.slice(3, size + 3);
138
141
  inBytes = inBytes.slice(size + 3);
@@ -143,8 +146,428 @@ const makeNoiseHandler = ({ keyPair: { private: privateKey, public: publicKey },
143
146
  logger.trace({ msg: (_a = frame === null || frame === void 0 ? void 0 : frame.attrs) === null || _a === void 0 ? void 0 : _a.id }, 'recv frame');
144
147
  onFrame(frame);
145
148
  size = getBytesSize();
149
+ if (size === 0) { inBytes = Buffer.alloc(0); throw new Error('NOISE_EMPTY_FRAME'); }
146
150
  }
147
151
  }
148
152
  };
149
153
  };
150
154
  exports.makeNoiseHandler = makeNoiseHandler;
155
+
156
+ // Kage: compatibilidad de API.
157
+ const __kageModule75 = (() => {
158
+ const module = { exports: {} }; const exports = module.exports;
159
+ "use strict"
160
+
161
+ Object.defineProperty(exports, "__esModule", { value: true })
162
+
163
+ const { Boom } = require("@hapi/boom")
164
+ const { proto } = require("../../WAProto")
165
+ const {
166
+ NOISE_MODE,
167
+ WA_CERT_DETAILS
168
+ } = require("../Defaults/constants")
169
+ const { decodeBinaryNode } = require("../WABinary")
170
+ const {
171
+ aesDecryptGCM,
172
+ aesEncryptGCM,
173
+ Curve,
174
+ hkdf,
175
+ sha256
176
+ } = require("./crypto")
177
+
178
+ const generateIV = (counter) => {
179
+ const iv = new ArrayBuffer(12)
180
+ new DataView(iv).setUint32(8, counter)
181
+ return new Uint8Array(iv)
182
+ }
183
+
184
+ const makeNoiseHandler = ({ keyPair: { private: privateKey, public: publicKey }, NOISE_HEADER, logger, routingInfo }) => {
185
+ logger = logger.child({ class: 'ns' })
186
+
187
+ const authenticate = (data) => {
188
+ if (!isFinished) {
189
+ hash = sha256(Buffer.concat([hash, data]))
190
+ }
191
+ }
192
+
193
+ const encrypt = (plaintext) => {
194
+ const result = aesEncryptGCM(plaintext, encKey, generateIV(writeCounter), hash)
195
+ writeCounter += 1
196
+ authenticate(result)
197
+ return result
198
+ }
199
+
200
+ const decrypt = (ciphertext) => {
201
+ // before the handshake is finished, we use the same counter
202
+ // after handshake, the counters are different
203
+ const iv = generateIV(isFinished ? readCounter : writeCounter)
204
+ const result = aesDecryptGCM(ciphertext, decKey, iv, hash)
205
+
206
+ if (isFinished) {
207
+ readCounter += 1
208
+ }
209
+
210
+ else {
211
+ writeCounter += 1
212
+ }
213
+
214
+ authenticate(ciphertext)
215
+
216
+ return result
217
+ }
218
+
219
+ const localHKDF = async (data) => {
220
+ const key = await hkdf(Buffer.from(data), 64, { salt, info: '' })
221
+ return [key.slice(0, 32), key.slice(32)]
222
+ }
223
+
224
+ const mixIntoKey = async (data) => {
225
+ const [write, read] = await localHKDF(data)
226
+ salt = write
227
+ encKey = read
228
+ decKey = read
229
+ readCounter = 0
230
+ writeCounter = 0
231
+ }
232
+
233
+ const finishInit = async () => {
234
+ const [write, read] = await localHKDF(new Uint8Array(0))
235
+ encKey = write
236
+ decKey = read
237
+ hash = Buffer.from([])
238
+ readCounter = 0
239
+ writeCounter = 0
240
+ isFinished = true
241
+ }
242
+
243
+ const data = Buffer.from(NOISE_MODE)
244
+
245
+ let hash = data.byteLength === 32 ? data : sha256(data)
246
+ let salt = hash
247
+ let encKey = hash
248
+ let decKey = hash
249
+ let readCounter = 0
250
+ let writeCounter = 0
251
+ let isFinished = false
252
+ let sentIntro = false
253
+ let inBytes = Buffer.alloc(0)
254
+
255
+ authenticate(NOISE_HEADER)
256
+ authenticate(publicKey)
257
+
258
+ return {
259
+ encrypt,
260
+ decrypt,
261
+ authenticate,
262
+ mixIntoKey,
263
+ finishInit,
264
+ processHandshake: async ({ serverHello }, noiseKey) => {
265
+ authenticate(serverHello.ephemeral)
266
+ await mixIntoKey(Curve.sharedKey(privateKey, serverHello.ephemeral))
267
+ const decStaticContent = decrypt(serverHello.static)
268
+ await mixIntoKey(Curve.sharedKey(privateKey, decStaticContent))
269
+ const certDecoded = decrypt(serverHello.payload)
270
+ const { intermediate: certIntermediate /*leaf*/ } = proto.CertChain.decode(certDecoded)
271
+ // TODO: handle this leaf stuff
272
+ const { issuerSerial } = proto.CertChain.NoiseCertificate.Details.decode(certIntermediate.details)
273
+
274
+ if (issuerSerial !== WA_CERT_DETAILS.SERIAL) {
275
+ throw new Boom('certification match failed', { statusCode: 400 })
276
+ }
277
+
278
+ const keyEnc = encrypt(noiseKey.public)
279
+
280
+ await mixIntoKey(Curve.sharedKey(noiseKey.private, serverHello.ephemeral))
281
+
282
+ return keyEnc
283
+ },
284
+ encodeFrame: (data) => {
285
+ if (isFinished) {
286
+ data = encrypt(data)
287
+ }
288
+
289
+ let header
290
+
291
+ if (routingInfo) {
292
+ header = Buffer.alloc(7)
293
+ header.write('ED', 0, 'utf8')
294
+ header.writeUint8(0, 2)
295
+ header.writeUint8(1, 3)
296
+ header.writeUint8(routingInfo.byteLength >> 16, 4)
297
+ header.writeUint16BE(routingInfo.byteLength & 65535, 5)
298
+ header = Buffer.concat([header, routingInfo, NOISE_HEADER])
299
+ }
300
+ else {
301
+ header = Buffer.from(NOISE_HEADER)
302
+ }
303
+
304
+ const introSize = sentIntro ? 0 : header.length
305
+ const frame = Buffer.alloc(introSize + 3 + data.byteLength)
306
+
307
+ if (!sentIntro) {
308
+ frame.set(header)
309
+ sentIntro = true
310
+ }
311
+
312
+ frame.writeUInt8(data.byteLength >> 16, introSize)
313
+ frame.writeUInt16BE(65535 & data.byteLength, introSize + 1)
314
+ frame.set(data, introSize + 3)
315
+ return frame
316
+ },
317
+ decodeFrame: async (newData, onFrame) => {
318
+ // the binary protocol uses its own framing mechanism
319
+ // on top of the WS frames
320
+ // so we get this data and separate out the frames
321
+ const getBytesSize = () => {
322
+ if (inBytes.length >= 3) {
323
+ return (inBytes.readUInt8() << 16) | inBytes.readUInt16BE(1)
324
+ }
325
+ }
326
+
327
+ inBytes = Buffer.concat([inBytes, newData])
328
+ logger.trace(`recv ${newData.length} bytes, total recv ${inBytes.length} bytes`)
329
+
330
+ let size = getBytesSize()
331
+ while (size && inBytes.length >= size + 3) {
332
+ let frame = inBytes.slice(3, size + 3)
333
+
334
+ inBytes = inBytes.slice(size + 3)
335
+
336
+ if (isFinished) {
337
+ const result = decrypt(frame)
338
+ frame = await decodeBinaryNode(result)
339
+ }
340
+
341
+ logger.trace({ msg: frame?.attrs?.id }, 'recv frame')
342
+
343
+ onFrame(frame)
344
+
345
+ size = getBytesSize()
346
+ }
347
+ }
348
+ }
349
+ }
350
+
351
+ module.exports = {
352
+ makeNoiseHandler
353
+ }
354
+ return module.exports;
355
+ })();
356
+ for (const key of Object.keys(__kageModule75)) {
357
+ if (key !== '__esModule' && !Object.prototype.hasOwnProperty.call(exports,key)) Object.defineProperty(exports,key,{enumerable:true,configurable:true,get:()=>__kageModule75[key]});
358
+ }
359
+
360
+ // Kage: funciones avanzadas.
361
+ const __kageModule179 = (() => {
362
+ const module = { exports: {} }; const exports = module.exports;
363
+ "use strict";
364
+ Object.defineProperty(exports, "__esModule", { value: true });
365
+ exports.makeNoiseHandler = void 0;
366
+ const index_js_1 = require("../../WAProto/index.js");
367
+ const index_js_2 = require("../Addon/index.js");
368
+ const index_js_3 = require("../Defaults/index.js");
369
+ const index_js_4 = require("../WABinary/index.js");
370
+ const crypto_js_1 = require("./crypto.js");
371
+ const IV_LENGTH = 12;
372
+ const EMPTY_BUFFER = Buffer.alloc(0);
373
+ const generateIV = (counter) => {
374
+ const iv = new ArrayBuffer(IV_LENGTH);
375
+ new DataView(iv).setUint32(8, counter);
376
+ return new Uint8Array(iv);
377
+ };
378
+ class TransportState {
379
+ constructor(encKey, decKey) {
380
+ this.encKey = encKey;
381
+ this.decKey = decKey;
382
+ this.readCounter = 0;
383
+ this.writeCounter = 0;
384
+ this.iv = new Uint8Array(IV_LENGTH);
385
+ }
386
+ encrypt(plaintext) {
387
+ const c = this.writeCounter++;
388
+ this.iv[8] = (c >>> 24) & 0xff;
389
+ this.iv[9] = (c >>> 16) & 0xff;
390
+ this.iv[10] = (c >>> 8) & 0xff;
391
+ this.iv[11] = c & 0xff;
392
+ return (0, crypto_js_1.aesEncryptGCM)(plaintext, this.encKey, this.iv, EMPTY_BUFFER);
393
+ }
394
+ decrypt(ciphertext) {
395
+ const c = this.readCounter++;
396
+ this.iv[8] = (c >>> 24) & 0xff;
397
+ this.iv[9] = (c >>> 16) & 0xff;
398
+ this.iv[10] = (c >>> 8) & 0xff;
399
+ this.iv[11] = c & 0xff;
400
+ return (0, crypto_js_1.aesDecryptGCM)(ciphertext, this.decKey, this.iv, EMPTY_BUFFER);
401
+ }
402
+ }
403
+ const makeNoiseHandler = ({ keyPair: { private: privateKey, public: publicKey }, NOISE_HEADER, logger, routingInfo }) => {
404
+ logger = logger.child({ class: 'ns' });
405
+ const data = Buffer.from(index_js_3.NOISE_MODE);
406
+ let hash = data.byteLength === 32 ? data : (0, crypto_js_1.sha256)(data);
407
+ let salt = hash;
408
+ let encKey = hash;
409
+ let decKey = hash;
410
+ let counter = 0;
411
+ let sentIntro = false;
412
+ let inBytes = Buffer.alloc(0);
413
+ let transport = null;
414
+ let isWaitingForTransport = false;
415
+ let pendingOnFrame = null;
416
+ let introHeader;
417
+ if (routingInfo) {
418
+ introHeader = Buffer.alloc(7 + routingInfo.byteLength + NOISE_HEADER.length);
419
+ introHeader.write('ED', 0, 'utf8');
420
+ introHeader.writeUint8(0, 2);
421
+ introHeader.writeUint8(1, 3);
422
+ introHeader.writeUint8(routingInfo.byteLength >> 16, 4);
423
+ introHeader.writeUint16BE(routingInfo.byteLength & 65535, 5);
424
+ introHeader.set(routingInfo, 7);
425
+ introHeader.set(NOISE_HEADER, 7 + routingInfo.byteLength);
426
+ }
427
+ else {
428
+ introHeader = Buffer.from(NOISE_HEADER);
429
+ }
430
+ const authenticate = (data) => {
431
+ if (!transport) {
432
+ hash = (0, crypto_js_1.sha256)(Buffer.concat([hash, data]));
433
+ }
434
+ };
435
+ const encrypt = (plaintext) => {
436
+ if (transport) {
437
+ return transport.encrypt(plaintext);
438
+ }
439
+ const result = (0, crypto_js_1.aesEncryptGCM)(plaintext, encKey, generateIV(counter++), hash);
440
+ authenticate(result);
441
+ return result;
442
+ };
443
+ const decrypt = (ciphertext) => {
444
+ if (transport) {
445
+ return transport.decrypt(ciphertext);
446
+ }
447
+ const result = (0, crypto_js_1.aesDecryptGCM)(ciphertext, decKey, generateIV(counter++), hash);
448
+ authenticate(ciphertext);
449
+ return result;
450
+ };
451
+ const localHKDF = (data) => {
452
+ const key = (0, crypto_js_1.hkdf)(Buffer.from(data), 64, { salt, info: '' });
453
+ return [key.subarray(0, 32), key.subarray(32)];
454
+ };
455
+ const mixIntoKey = (data) => {
456
+ const [write, read] = localHKDF(data);
457
+ salt = write;
458
+ encKey = read;
459
+ decKey = read;
460
+ counter = 0;
461
+ };
462
+ const finishInit = async () => {
463
+ isWaitingForTransport = true;
464
+ const [write, read] = localHKDF(new Uint8Array(0));
465
+ transport = new TransportState(write, read);
466
+ isWaitingForTransport = false;
467
+ logger.trace('Noise handler transitioned to Transport state');
468
+ if (pendingOnFrame) {
469
+ logger.trace({ length: inBytes.length }, 'Flushing buffered frames after transport ready');
470
+ await processData(pendingOnFrame);
471
+ pendingOnFrame = null;
472
+ }
473
+ };
474
+ const processData = async (onFrame) => {
475
+ let size;
476
+ while (true) {
477
+ if (inBytes.length < 3)
478
+ return;
479
+ size = (inBytes[0] << 16) | (inBytes[1] << 8) | inBytes[2];
480
+ if (inBytes.length < size + 3)
481
+ return;
482
+ let frame = inBytes.subarray(3, size + 3);
483
+ inBytes = inBytes.subarray(size + 3);
484
+ if (transport) {
485
+ const result = transport.decrypt(frame);
486
+ frame = await (0, index_js_4.decodeBinaryNode)(result);
487
+ }
488
+ if (logger.level === 'trace') {
489
+ logger.trace({ msg: frame?.attrs?.id }, 'recv frame');
490
+ }
491
+ onFrame(frame);
492
+ }
493
+ };
494
+ authenticate(NOISE_HEADER);
495
+ authenticate(publicKey);
496
+ return {
497
+ encrypt,
498
+ decrypt,
499
+ authenticate,
500
+ mixIntoKey,
501
+ finishInit,
502
+ processHandshake: ({ serverHello }, noiseKey) => {
503
+ authenticate(serverHello.ephemeral);
504
+ mixIntoKey(crypto_js_1.Curve.sharedKey(privateKey, serverHello.ephemeral));
505
+ const decStaticContent = decrypt(serverHello.static);
506
+ mixIntoKey(crypto_js_1.Curve.sharedKey(privateKey, decStaticContent));
507
+ const certDecoded = decrypt(serverHello.payload);
508
+ const { intermediate: certIntermediate, leaf } = index_js_1.proto.CertChain.decode(certDecoded);
509
+ // leaf
510
+ if (!leaf?.details || !leaf?.signature) {
511
+ throw new index_js_2.HttpError('invalid noise leaf certificate', { statusCode: 400 });
512
+ }
513
+ if (!certIntermediate?.details || !certIntermediate?.signature) {
514
+ throw new index_js_2.HttpError('invalid noise intermediate certificate', { statusCode: 400 });
515
+ }
516
+ const details = index_js_1.proto.CertChain.NoiseCertificate.Details.decode(certIntermediate.details);
517
+ const { issuerSerial } = details;
518
+ const verify = crypto_js_1.Curve.verify(details.key, leaf.details, leaf.signature);
519
+ const verifyIntermediate = crypto_js_1.Curve.verify(index_js_3.WA_CERT_DETAILS.PUBLIC_KEY, certIntermediate.details, certIntermediate.signature);
520
+ if (!verify) {
521
+ throw new index_js_2.HttpError('noise certificate signature invalid', { statusCode: 400 });
522
+ }
523
+ if (!verifyIntermediate) {
524
+ throw new index_js_2.HttpError('noise intermediate certificate signature invalid', { statusCode: 400 });
525
+ }
526
+ if (issuerSerial !== index_js_3.WA_CERT_DETAILS.SERIAL) {
527
+ throw new index_js_2.HttpError('certification match failed', { statusCode: 400 });
528
+ }
529
+ const keyEnc = encrypt(noiseKey.public);
530
+ mixIntoKey(crypto_js_1.Curve.sharedKey(noiseKey.private, serverHello.ephemeral));
531
+ return keyEnc;
532
+ },
533
+ encodeFrame: (data) => {
534
+ if (transport) {
535
+ data = transport.encrypt(data);
536
+ }
537
+ const dataLen = data.byteLength;
538
+ const introSize = sentIntro ? 0 : introHeader.length;
539
+ const frame = Buffer.allocUnsafe(introSize + 3 + dataLen);
540
+ if (!sentIntro) {
541
+ frame.set(introHeader);
542
+ sentIntro = true;
543
+ }
544
+ frame[introSize] = (dataLen >>> 16) & 0xff;
545
+ frame[introSize + 1] = (dataLen >>> 8) & 0xff;
546
+ frame[introSize + 2] = dataLen & 0xff;
547
+ frame.set(data, introSize + 3);
548
+ return frame;
549
+ },
550
+ decodeFrame: async (newData, onFrame) => {
551
+ if (isWaitingForTransport) {
552
+ inBytes = Buffer.concat([inBytes, newData]);
553
+ pendingOnFrame = onFrame;
554
+ return;
555
+ }
556
+ if (inBytes.length === 0) {
557
+ inBytes = Buffer.from(newData);
558
+ }
559
+ else {
560
+ inBytes = Buffer.concat([inBytes, newData]);
561
+ }
562
+ await processData(onFrame);
563
+ }
564
+ };
565
+ };
566
+ exports.makeNoiseHandler = makeNoiseHandler;
567
+
568
+ return module.exports;
569
+ })();
570
+ for (const key of Object.keys(__kageModule179)) {
571
+ if (key !== '__esModule' && !Object.prototype.hasOwnProperty.call(exports,key)) Object.defineProperty(exports,key,{enumerable:true,configurable:true,get:()=>__kageModule179[key]});
572
+ }
573
+ Object.defineProperty(exports, Symbol.for('kage.advanced'), {value:__kageModule179, configurable:true});
@@ -37,4 +37,56 @@
37
37
  };
38
38
  return { enqueue };
39
39
  } exports.makeOfflineNodeProcessor = makeOfflineNodeProcessor;
40
- //# sourceMappingURL=offline-node-processor.js.map
40
+ //#
41
+ // Kage: funciones avanzadas.
42
+ const __kageModule180 = (() => {
43
+ const module = { exports: {} }; const exports = module.exports;
44
+ "use strict";
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.makeOfflineNodeProcessor = makeOfflineNodeProcessor;
47
+ /**
48
+ * Creates a processor for offline stanza nodes that:
49
+ * - Queues nodes for sequential processing
50
+ * - Yields to the event loop periodically to avoid blocking
51
+ * - Catches handler errors to prevent the processing loop from crashing
52
+ */
53
+ function makeOfflineNodeProcessor(nodeProcessorMap, deps, batchSize = 10) {
54
+ const nodes = [];
55
+ let isProcessing = false;
56
+ const enqueue = (type, node) => {
57
+ nodes.push({ type, node });
58
+ if (isProcessing) {
59
+ return;
60
+ }
61
+ isProcessing = true;
62
+ const promise = async () => {
63
+ let processedInBatch = 0;
64
+ while (nodes.length && deps.isWsOpen()) {
65
+ const { type, node } = nodes.shift();
66
+ const nodeProcessor = nodeProcessorMap.get(type);
67
+ if (!nodeProcessor) {
68
+ deps.onUnexpectedError(new Error(`unknown offline node type: ${type}`), 'processing offline node');
69
+ continue;
70
+ }
71
+ await nodeProcessor(node).catch(err => deps.onUnexpectedError(err, `processing offline ${type}`));
72
+ processedInBatch++;
73
+ // Yield to event loop after processing a batch
74
+ // This prevents blocking the event loop for too long when there are many offline nodes
75
+ if (processedInBatch >= batchSize) {
76
+ processedInBatch = 0;
77
+ await deps.yieldToEventLoop();
78
+ }
79
+ }
80
+ isProcessing = false;
81
+ };
82
+ promise().catch(error => deps.onUnexpectedError(error, 'processing offline nodes'));
83
+ };
84
+ return { enqueue };
85
+ }
86
+
87
+ return module.exports;
88
+ })();
89
+ for (const key of Object.keys(__kageModule180)) {
90
+ if (key !== '__esModule' && !Object.prototype.hasOwnProperty.call(exports,key)) Object.defineProperty(exports,key,{enumerable:true,configurable:true,get:()=>__kageModule180[key]});
91
+ }
92
+ Object.defineProperty(exports, Symbol.for('kage.advanced'), {value:__kageModule180, configurable:true});