@zentrix/baileys 4.1.5

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 (200) hide show
  1. package/README.md +202 -0
  2. package/WAProto/index.js +169661 -0
  3. package/engine-requirements.js +10 -0
  4. package/lib/Defaults/baileys-version.json +3 -0
  5. package/lib/Defaults/index.d.ts +53 -0
  6. package/lib/Defaults/index.js +147 -0
  7. package/lib/Defaults/phonenumber-mcc.json +223 -0
  8. package/lib/Signal/Group/ciphertext-message.d.ts +9 -0
  9. package/lib/Signal/Group/ciphertext-message.js +15 -0
  10. package/lib/Signal/Group/group-session-builder.d.ts +14 -0
  11. package/lib/Signal/Group/group-session-builder.js +64 -0
  12. package/lib/Signal/Group/group_cipher.d.ts +17 -0
  13. package/lib/Signal/Group/group_cipher.js +96 -0
  14. package/lib/Signal/Group/index.d.ts +11 -0
  15. package/lib/Signal/Group/index.js +57 -0
  16. package/lib/Signal/Group/keyhelper.d.ts +10 -0
  17. package/lib/Signal/Group/keyhelper.js +55 -0
  18. package/lib/Signal/Group/queue-job.d.ts +1 -0
  19. package/lib/Signal/Group/queue-job.js +57 -0
  20. package/lib/Signal/Group/sender-chain-key.d.ts +13 -0
  21. package/lib/Signal/Group/sender-chain-key.js +34 -0
  22. package/lib/Signal/Group/sender-key-distribution-message.d.ts +16 -0
  23. package/lib/Signal/Group/sender-key-distribution-message.js +66 -0
  24. package/lib/Signal/Group/sender-key-message.d.ts +18 -0
  25. package/lib/Signal/Group/sender-key-message.js +69 -0
  26. package/lib/Signal/Group/sender-key-name.d.ts +17 -0
  27. package/lib/Signal/Group/sender-key-name.js +51 -0
  28. package/lib/Signal/Group/sender-key-record.d.ts +30 -0
  29. package/lib/Signal/Group/sender-key-record.js +53 -0
  30. package/lib/Signal/Group/sender-key-state.d.ts +38 -0
  31. package/lib/Signal/Group/sender-key-state.js +99 -0
  32. package/lib/Signal/Group/sender-message-key.d.ts +11 -0
  33. package/lib/Signal/Group/sender-message-key.js +29 -0
  34. package/lib/Signal/libsignal.d.ts +3 -0
  35. package/lib/Signal/libsignal.js +336 -0
  36. package/lib/Signal/lid-mapping.js +293 -0
  37. package/lib/Socket/Client/abstract-socket-client.d.ts +17 -0
  38. package/lib/Socket/Client/abstract-socket-client.js +13 -0
  39. package/lib/Socket/Client/index.d.ts +3 -0
  40. package/lib/Socket/Client/index.js +19 -0
  41. package/lib/Socket/Client/mobile-socket-client.d.ts +13 -0
  42. package/lib/Socket/Client/mobile-socket-client.js +65 -0
  43. package/lib/Socket/Client/web-socket-client.d.ts +12 -0
  44. package/lib/Socket/Client/web-socket-client.js +62 -0
  45. package/lib/Socket/business.d.ts +171 -0
  46. package/lib/Socket/business.js +260 -0
  47. package/lib/Socket/chats.d.ts +267 -0
  48. package/lib/Socket/chats.js +970 -0
  49. package/lib/Socket/groups.d.ts +115 -0
  50. package/lib/Socket/groups.js +334 -0
  51. package/lib/Socket/index.d.ts +173 -0
  52. package/lib/Socket/index.js +11 -0
  53. package/lib/Socket/luxu.d.ts +268 -0
  54. package/lib/Socket/luxu.js +591 -0
  55. package/lib/Socket/messages-recv.d.ts +161 -0
  56. package/lib/Socket/messages-recv.js +1126 -0
  57. package/lib/Socket/messages-send.d.ts +149 -0
  58. package/lib/Socket/messages-send.js +913 -0
  59. package/lib/Socket/newsletter.d.ts +134 -0
  60. package/lib/Socket/newsletter.js +315 -0
  61. package/lib/Socket/registration.d.ts +267 -0
  62. package/lib/Socket/registration.js +166 -0
  63. package/lib/Socket/socket.d.ts +43 -0
  64. package/lib/Socket/socket.js +688 -0
  65. package/lib/Socket/usync.d.ts +36 -0
  66. package/lib/Socket/usync.js +70 -0
  67. package/lib/Store/index.d.ts +3 -0
  68. package/lib/Store/index.js +10 -0
  69. package/lib/Store/make-cache-manager-store.d.ts +13 -0
  70. package/lib/Store/make-cache-manager-store.js +83 -0
  71. package/lib/Store/make-in-memory-store.d.ts +118 -0
  72. package/lib/Store/make-in-memory-store.js +427 -0
  73. package/lib/Store/make-ordered-dictionary.d.ts +13 -0
  74. package/lib/Store/make-ordered-dictionary.js +81 -0
  75. package/lib/Store/object-repository.d.ts +10 -0
  76. package/lib/Store/object-repository.js +27 -0
  77. package/lib/Types/Auth.d.ts +110 -0
  78. package/lib/Types/Auth.js +2 -0
  79. package/lib/Types/Call.d.ts +13 -0
  80. package/lib/Types/Call.js +2 -0
  81. package/lib/Types/Chat.d.ts +102 -0
  82. package/lib/Types/Chat.js +4 -0
  83. package/lib/Types/Contact.d.ts +19 -0
  84. package/lib/Types/Contact.js +2 -0
  85. package/lib/Types/Events.d.ts +157 -0
  86. package/lib/Types/Events.js +2 -0
  87. package/lib/Types/GroupMetadata.d.ts +55 -0
  88. package/lib/Types/GroupMetadata.js +2 -0
  89. package/lib/Types/Label.d.ts +35 -0
  90. package/lib/Types/Label.js +27 -0
  91. package/lib/Types/LabelAssociation.d.ts +29 -0
  92. package/lib/Types/LabelAssociation.js +9 -0
  93. package/lib/Types/Message.d.ts +273 -0
  94. package/lib/Types/Message.js +9 -0
  95. package/lib/Types/Newsletter.d.ts +103 -0
  96. package/lib/Types/Newsletter.js +38 -0
  97. package/lib/Types/Product.d.ts +78 -0
  98. package/lib/Types/Product.js +2 -0
  99. package/lib/Types/Signal.d.ts +57 -0
  100. package/lib/Types/Signal.js +2 -0
  101. package/lib/Types/Socket.d.ts +111 -0
  102. package/lib/Types/Socket.js +2 -0
  103. package/lib/Types/State.d.ts +27 -0
  104. package/lib/Types/State.js +2 -0
  105. package/lib/Types/USync.d.ts +25 -0
  106. package/lib/Types/USync.js +2 -0
  107. package/lib/Types/index.d.ts +57 -0
  108. package/lib/Types/index.js +42 -0
  109. package/lib/Utils/auth-utils.d.ts +18 -0
  110. package/lib/Utils/auth-utils.js +206 -0
  111. package/lib/Utils/baileys-event-stream.d.ts +16 -0
  112. package/lib/Utils/baileys-event-stream.js +63 -0
  113. package/lib/Utils/business.d.ts +22 -0
  114. package/lib/Utils/business.js +234 -0
  115. package/lib/Utils/chat-utils.d.ts +71 -0
  116. package/lib/Utils/chat-utils.js +729 -0
  117. package/lib/Utils/crypto.d.ts +41 -0
  118. package/lib/Utils/crypto.js +151 -0
  119. package/lib/Utils/decode-wa-message.d.ts +19 -0
  120. package/lib/Utils/decode-wa-message.js +243 -0
  121. package/lib/Utils/event-buffer.d.ts +35 -0
  122. package/lib/Utils/event-buffer.js +514 -0
  123. package/lib/Utils/generics.d.ts +92 -0
  124. package/lib/Utils/generics.js +423 -0
  125. package/lib/Utils/history.d.ts +15 -0
  126. package/lib/Utils/history.js +96 -0
  127. package/lib/Utils/identity-change-handler.js +68 -0
  128. package/lib/Utils/index.d.ts +17 -0
  129. package/lib/Utils/index.js +41 -0
  130. package/lib/Utils/link-preview.d.ts +21 -0
  131. package/lib/Utils/link-preview.js +93 -0
  132. package/lib/Utils/logger.d.ts +4 -0
  133. package/lib/Utils/logger.js +7 -0
  134. package/lib/Utils/lt-hash.d.ts +12 -0
  135. package/lib/Utils/lt-hash.js +51 -0
  136. package/lib/Utils/make-mutex.d.ts +7 -0
  137. package/lib/Utils/make-mutex.js +43 -0
  138. package/lib/Utils/message-retry-manager.js +192 -0
  139. package/lib/Utils/messages-media.d.ts +116 -0
  140. package/lib/Utils/messages-media.js +819 -0
  141. package/lib/Utils/messages.d.ts +77 -0
  142. package/lib/Utils/messages.js +816 -0
  143. package/lib/Utils/noise-handler.d.ts +21 -0
  144. package/lib/Utils/noise-handler.js +155 -0
  145. package/lib/Utils/offline-node-processor.js +55 -0
  146. package/lib/Utils/pre-key-manager.js +95 -0
  147. package/lib/Utils/process-message.d.ts +41 -0
  148. package/lib/Utils/process-message.js +321 -0
  149. package/lib/Utils/signal.d.ts +32 -0
  150. package/lib/Utils/signal.js +153 -0
  151. package/lib/Utils/stanza-ack.js +47 -0
  152. package/lib/Utils/tc-token-utils.js +173 -0
  153. package/lib/Utils/use-multi-file-auth-state.d.ts +13 -0
  154. package/lib/Utils/use-multi-file-auth-state.js +119 -0
  155. package/lib/Utils/validate-connection.d.ts +11 -0
  156. package/lib/Utils/validate-connection.js +229 -0
  157. package/lib/WABinary/constants.d.ts +30 -0
  158. package/lib/WABinary/constants.js +40 -0
  159. package/lib/WABinary/decode.d.ts +7 -0
  160. package/lib/WABinary/decode.js +252 -0
  161. package/lib/WABinary/encode.d.ts +3 -0
  162. package/lib/WABinary/encode.js +265 -0
  163. package/lib/WABinary/generic-utils.d.ts +17 -0
  164. package/lib/WABinary/generic-utils.js +198 -0
  165. package/lib/WABinary/index.d.ts +5 -0
  166. package/lib/WABinary/index.js +21 -0
  167. package/lib/WABinary/jid-utils.d.ts +31 -0
  168. package/lib/WABinary/jid-utils.js +138 -0
  169. package/lib/WABinary/types.d.ts +18 -0
  170. package/lib/WABinary/types.js +2 -0
  171. package/lib/WAM/BinaryInfo.d.ts +17 -0
  172. package/lib/WAM/BinaryInfo.js +13 -0
  173. package/lib/WAM/constants.d.ts +38 -0
  174. package/lib/WAM/constants.js +15350 -0
  175. package/lib/WAM/encode.d.ts +3 -0
  176. package/lib/WAM/encode.js +155 -0
  177. package/lib/WAM/index.d.ts +3 -0
  178. package/lib/WAM/index.js +19 -0
  179. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +9 -0
  180. package/lib/WAUSync/Protocols/USyncContactProtocol.js +32 -0
  181. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +22 -0
  182. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +57 -0
  183. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -0
  184. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +30 -0
  185. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -0
  186. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +42 -0
  187. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +25 -0
  188. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +53 -0
  189. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +8 -0
  190. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +24 -0
  191. package/lib/WAUSync/Protocols/index.d.ts +4 -0
  192. package/lib/WAUSync/Protocols/index.js +20 -0
  193. package/lib/WAUSync/USyncQuery.d.ts +28 -0
  194. package/lib/WAUSync/USyncQuery.js +89 -0
  195. package/lib/WAUSync/USyncUser.d.ts +12 -0
  196. package/lib/WAUSync/USyncUser.js +26 -0
  197. package/lib/WAUSync/index.js +19 -0
  198. package/lib/index.d.ts +12 -0
  199. package/lib/index.js +35 -0
  200. package/package.json +108 -0
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SenderKeyState = void 0;
4
+ const sender_chain_key_1 = require("./sender-chain-key");
5
+ const sender_message_key_1 = require("./sender-message-key");
6
+ class SenderKeyState {
7
+ constructor(id, iteration, chainKey, signatureKeyPair, signatureKeyPublic, signatureKeyPrivate, senderKeyStateStructure) {
8
+ this.MAX_MESSAGE_KEYS = 2000;
9
+ if (senderKeyStateStructure) {
10
+ this.senderKeyStateStructure = senderKeyStateStructure;
11
+ }
12
+ else {
13
+ if (signatureKeyPair) {
14
+ signatureKeyPublic = signatureKeyPair.public;
15
+ signatureKeyPrivate = signatureKeyPair.private;
16
+ }
17
+ chainKey = typeof chainKey === 'string' ? Buffer.from(chainKey, 'base64') : chainKey;
18
+ const senderChainKeyStructure = {
19
+ iteration: iteration || 0,
20
+ seed: chainKey || Buffer.alloc(0)
21
+ };
22
+ const signingKeyStructure = {
23
+ public: typeof signatureKeyPublic === 'string'
24
+ ? Buffer.from(signatureKeyPublic, 'base64')
25
+ : signatureKeyPublic || Buffer.alloc(0)
26
+ };
27
+ if (signatureKeyPrivate) {
28
+ signingKeyStructure.private =
29
+ typeof signatureKeyPrivate === 'string' ? Buffer.from(signatureKeyPrivate, 'base64') : signatureKeyPrivate;
30
+ }
31
+ this.senderKeyStateStructure = {
32
+ senderKeyId: id || 0,
33
+ senderChainKey: senderChainKeyStructure,
34
+ senderSigningKey: signingKeyStructure,
35
+ senderMessageKeys: []
36
+ };
37
+ }
38
+ }
39
+ getKeyId() {
40
+ return this.senderKeyStateStructure.senderKeyId;
41
+ }
42
+ getSenderChainKey() {
43
+ return new sender_chain_key_1.SenderChainKey(this.senderKeyStateStructure.senderChainKey.iteration, this.senderKeyStateStructure.senderChainKey.seed);
44
+ }
45
+ setSenderChainKey(chainKey) {
46
+ this.senderKeyStateStructure.senderChainKey = {
47
+ iteration: chainKey.getIteration(),
48
+ seed: chainKey.getSeed()
49
+ };
50
+ }
51
+ getSigningKeyPublic() {
52
+ const publicKey = this.senderKeyStateStructure.senderSigningKey.public;
53
+ if (publicKey instanceof Buffer) {
54
+ return publicKey;
55
+ }
56
+ else if (typeof publicKey === 'string') {
57
+ return Buffer.from(publicKey, 'base64');
58
+ }
59
+ return Buffer.from(publicKey || []);
60
+ }
61
+ getSigningKeyPrivate() {
62
+ const privateKey = this.senderKeyStateStructure.senderSigningKey.private;
63
+ if (!privateKey) {
64
+ return undefined;
65
+ }
66
+ if (privateKey instanceof Buffer) {
67
+ return privateKey;
68
+ }
69
+ else if (typeof privateKey === 'string') {
70
+ return Buffer.from(privateKey, 'base64');
71
+ }
72
+ return Buffer.from(privateKey || []);
73
+ }
74
+ hasSenderMessageKey(iteration) {
75
+ return this.senderKeyStateStructure.senderMessageKeys.some(key => key.iteration === iteration);
76
+ }
77
+ addSenderMessageKey(senderMessageKey) {
78
+ this.senderKeyStateStructure.senderMessageKeys.push({
79
+ iteration: senderMessageKey.getIteration(),
80
+ seed: senderMessageKey.getSeed()
81
+ });
82
+ if (this.senderKeyStateStructure.senderMessageKeys.length > this.MAX_MESSAGE_KEYS) {
83
+ this.senderKeyStateStructure.senderMessageKeys.shift();
84
+ }
85
+ }
86
+ removeSenderMessageKey(iteration) {
87
+ const index = this.senderKeyStateStructure.senderMessageKeys.findIndex(key => key.iteration === iteration);
88
+ if (index !== -1) {
89
+ const messageKey = this.senderKeyStateStructure.senderMessageKeys[index];
90
+ this.senderKeyStateStructure.senderMessageKeys.splice(index, 1);
91
+ return new sender_message_key_1.SenderMessageKey(messageKey.iteration, messageKey.seed);
92
+ }
93
+ return null;
94
+ }
95
+ getStructure() {
96
+ return this.senderKeyStateStructure;
97
+ }
98
+ }
99
+ exports.SenderKeyState = SenderKeyState;
@@ -0,0 +1,11 @@
1
+ export declare class SenderMessageKey {
2
+ private readonly iteration;
3
+ private readonly iv;
4
+ private readonly cipherKey;
5
+ private readonly seed;
6
+ constructor(iteration: number, seed: Uint8Array);
7
+ getIteration(): number;
8
+ getIv(): Uint8Array;
9
+ getCipherKey(): Uint8Array;
10
+ getSeed(): Uint8Array;
11
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SenderMessageKey = void 0;
4
+ const crypto_1 = require("libsignal/src/crypto");
5
+ class SenderMessageKey {
6
+ constructor(iteration, seed) {
7
+ const derivative = (0, crypto_1.deriveSecrets)(seed, Buffer.alloc(32), Buffer.from('WhisperGroup'));
8
+ const keys = new Uint8Array(32);
9
+ keys.set(new Uint8Array(derivative[0].slice(16)));
10
+ keys.set(new Uint8Array(derivative[1].slice(0, 16)), 16);
11
+ this.iv = Buffer.from(derivative[0].slice(0, 16));
12
+ this.cipherKey = Buffer.from(keys.buffer);
13
+ this.iteration = iteration;
14
+ this.seed = seed;
15
+ }
16
+ getIteration() {
17
+ return this.iteration;
18
+ }
19
+ getIv() {
20
+ return this.iv;
21
+ }
22
+ getCipherKey() {
23
+ return this.cipherKey;
24
+ }
25
+ getSeed() {
26
+ return this.seed;
27
+ }
28
+ }
29
+ exports.SenderMessageKey = SenderMessageKey;
@@ -0,0 +1,3 @@
1
+ import { SignalAuthState } from '../Types';
2
+ import { SignalRepository } from '../Types/Signal';
3
+ export declare function makeLibSignalRepository(auth: SignalAuthState): SignalRepository;
@@ -0,0 +1,336 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.makeLibSignalRepository = makeLibSignalRepository;
37
+ const libsignal = __importStar(require("libsignal"));
38
+ const Utils_1 = require("../Utils");
39
+ const WABinary_1 = require("../WABinary");
40
+ const sender_key_name_1 = require("./Group/sender-key-name");
41
+ const sender_key_record_1 = require("./Group/sender-key-record");
42
+ const Group_1 = require("./Group");
43
+
44
+ /**
45
+ * FIX 1: Identity key extraction from PreKeyWhisperMessage.
46
+ * Allows detecting identity changes BEFORE decryption, preventing Bad MAC errors
47
+ * caused by stale sessions with a contact who has re-registered or changed devices.
48
+ */
49
+ function extractIdentityFromPkmsg(ciphertext) {
50
+ try {
51
+ if (!ciphertext || ciphertext.length < 2) return undefined;
52
+ // Version byte check (must be version 3)
53
+ const version = ciphertext[0];
54
+ if ((version & 0xf) !== 3) return undefined;
55
+ // Minimal protobuf parse to extract identityKey field (tag 4, wire type 2)
56
+ const data = ciphertext.slice(1);
57
+ let i = 0;
58
+ while (i < data.length) {
59
+ const tag = data[i] >> 3;
60
+ const wireType = data[i] & 0x7;
61
+ i++;
62
+ if (wireType === 2) {
63
+ // length-delimited
64
+ let len = 0, shift = 0;
65
+ while (i < data.length) {
66
+ const b = data[i++];
67
+ len |= (b & 0x7f) << shift;
68
+ if (!(b & 0x80)) break;
69
+ shift += 7;
70
+ }
71
+ if (tag === 4 && len === 33) {
72
+ // identityKey field
73
+ return new Uint8Array(data.slice(i, i + len));
74
+ }
75
+ i += len;
76
+ } else if (wireType === 0) {
77
+ // varint - skip
78
+ while (i < data.length && (data[i++] & 0x80));
79
+ } else if (wireType === 5) {
80
+ i += 4;
81
+ } else if (wireType === 1) {
82
+ i += 8;
83
+ } else {
84
+ break;
85
+ }
86
+ }
87
+ return undefined;
88
+ } catch {
89
+ return undefined;
90
+ }
91
+ }
92
+
93
+ function makeLibSignalRepository(auth, logger) {
94
+ const storage = signalStorage(auth, logger);
95
+
96
+ return {
97
+ decryptGroupMessage({ group, authorJid, msg }) {
98
+ const senderName = jidToSignalSenderKeyName(group, authorJid);
99
+ const cipher = new Group_1.GroupCipher(storage, senderName);
100
+ return cipher.decrypt(msg);
101
+ },
102
+
103
+ async processSenderKeyDistributionMessage({ item, authorJid }) {
104
+ const builder = new Group_1.GroupSessionBuilder(storage);
105
+ if (!item.groupId) {
106
+ throw new Error('Group ID is required for sender key distribution message');
107
+ }
108
+ const senderName = jidToSignalSenderKeyName(item.groupId, authorJid);
109
+ const senderMsg = new Group_1.SenderKeyDistributionMessage(null, null, null, null, item.axolotlSenderKeyDistributionMessage);
110
+ const senderNameStr = senderName.toString();
111
+ const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr]);
112
+ if (!senderKey) {
113
+ await storage.storeSenderKey(senderName, new sender_key_record_1.SenderKeyRecord());
114
+ }
115
+ await builder.process(senderName, senderMsg);
116
+ },
117
+
118
+ async decryptMessage({ jid, type, ciphertext }) {
119
+ const addr = jidToSignalProtocolAddress(jid);
120
+ const session = new libsignal.SessionCipher(storage, addr);
121
+
122
+ /**
123
+ * FIX 2: Identity key change detection before decryption.
124
+ * When we receive a pkmsg (PreKey message = new session establishment),
125
+ * extract and save the sender's identity key FIRST.
126
+ * If the identity changed (re-registered number), clear old session.
127
+ * This prevents Bad MAC errors from trying to decrypt with stale keys.
128
+ */
129
+ if (type === 'pkmsg') {
130
+ const identityKey = extractIdentityFromPkmsg(ciphertext);
131
+ if (identityKey) {
132
+ const addrStr = addr.toString();
133
+ const identityChanged = await storage.saveIdentity(addrStr, identityKey);
134
+ if (identityChanged && logger) {
135
+ logger.info({ jid, addr: addrStr }, 'identity key changed, session will be re-established');
136
+ }
137
+ }
138
+ }
139
+
140
+ let result;
141
+ switch (type) {
142
+ case 'pkmsg':
143
+ result = await session.decryptPreKeyWhisperMessage(ciphertext);
144
+ break;
145
+ case 'msg':
146
+ result = await session.decryptWhisperMessage(ciphertext);
147
+ break;
148
+ default:
149
+ throw new Error(`Unknown message type: ${type}`);
150
+ }
151
+ return result;
152
+ },
153
+
154
+ async encryptMessage({ jid, data }) {
155
+ const addr = jidToSignalProtocolAddress(jid);
156
+ const cipher = new libsignal.SessionCipher(storage, addr);
157
+ const { type: sigType, body } = await cipher.encrypt(data);
158
+ const type = sigType === 3 ? 'pkmsg' : 'msg';
159
+ return { type, ciphertext: Buffer.from(body, 'binary') };
160
+ },
161
+
162
+ async encryptGroupMessage({ group, meId, data }) {
163
+ const senderName = jidToSignalSenderKeyName(group, meId);
164
+ const builder = new Group_1.GroupSessionBuilder(storage);
165
+ const senderNameStr = senderName.toString();
166
+ const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr]);
167
+ if (!senderKey) {
168
+ await storage.storeSenderKey(senderName, new sender_key_record_1.SenderKeyRecord());
169
+ }
170
+ const senderKeyDistributionMessage = await builder.create(senderName);
171
+ const session = new Group_1.GroupCipher(storage, senderName);
172
+ const ciphertext = await session.encrypt(data);
173
+ return {
174
+ ciphertext,
175
+ senderKeyDistributionMessage: senderKeyDistributionMessage.serialize()
176
+ };
177
+ },
178
+
179
+ async injectE2ESession({ jid, session }) {
180
+ const cipher = new libsignal.SessionBuilder(storage, jidToSignalProtocolAddress(jid));
181
+ await cipher.initOutgoing(session);
182
+ },
183
+
184
+ jidToSignalProtocolAddress(jid) {
185
+ return jidToSignalProtocolAddress(jid).toString();
186
+ },
187
+
188
+ /**
189
+ * FIX 3: validateSession - check if a valid open session exists for a JID.
190
+ * Used by the retry system to decide whether to force re-key before retrying.
191
+ */
192
+ async validateSession(jid) {
193
+ try {
194
+ const addr = jidToSignalProtocolAddress(jid);
195
+ const sess = await storage.loadSession(addr.toString());
196
+ if (!sess) return { exists: false, reason: 'no session' };
197
+ if (!sess.haveOpenSession()) return { exists: false, reason: 'no open session' };
198
+ return { exists: true };
199
+ } catch (error) {
200
+ return { exists: false, reason: 'validation error' };
201
+ }
202
+ },
203
+
204
+ /**
205
+ * FIX 4: deleteSession - bulk-delete sessions by JID list.
206
+ * Used to force re-establishment of broken/corrupt sessions
207
+ * rather than letting Bad MAC errors loop indefinitely.
208
+ */
209
+ async deleteSession(jids) {
210
+ if (!jids || !jids.length) return;
211
+ const sessionUpdates = {};
212
+ jids.forEach(jid => {
213
+ const addr = jidToSignalProtocolAddress(jid);
214
+ sessionUpdates[addr.toString()] = null;
215
+ });
216
+ await auth.keys.set({ session: sessionUpdates });
217
+ }
218
+ };
219
+ }
220
+
221
+ const jidToSignalProtocolAddress = (jid) => {
222
+ const { user, device } = (0, WABinary_1.jidDecode)(jid);
223
+ return new libsignal.ProtocolAddress(user, device || 0);
224
+ };
225
+
226
+ const jidToSignalSenderKeyName = (group, user) => {
227
+ return new sender_key_name_1.SenderKeyName(group, jidToSignalProtocolAddress(user));
228
+ };
229
+
230
+ function signalStorage({ creds, keys }, logger) {
231
+ return {
232
+ loadSession: async (id) => {
233
+ try {
234
+ const { [id]: sess } = await keys.get('session', [id]);
235
+ if (sess) {
236
+ return libsignal.SessionRecord.deserialize(sess);
237
+ }
238
+ } catch (e) {
239
+ if (logger) logger.warn({ id, err: e }, 'failed to load session, returning null');
240
+ return null;
241
+ }
242
+ return null;
243
+ },
244
+
245
+ storeSession: async (id, session) => {
246
+ await keys.set({ session: { [id]: session.serialize() } });
247
+ },
248
+
249
+ isTrustedIdentity: () => {
250
+ return true; // TOFU - Trust on First Use
251
+ },
252
+
253
+ /**
254
+ * FIX 5: loadIdentityKey - expose identity key loading.
255
+ * Required for identity change detection in saveIdentity.
256
+ */
257
+ loadIdentityKey: async (id) => {
258
+ const { [id]: key } = await keys.get('identity-key', [id]);
259
+ return key || undefined;
260
+ },
261
+
262
+ /**
263
+ * FIX 6: saveIdentity - detect identity key changes.
264
+ * When a contact re-registers their number, their identity key changes.
265
+ * Old sessions using the previous key will produce Bad MAC on every message.
266
+ * This clears the stale session and saves the new key so re-keying happens.
267
+ */
268
+ saveIdentity: async (id, identityKey) => {
269
+ const { [id]: existingKey } = await keys.get('identity-key', [id]);
270
+ const keysMatch = existingKey &&
271
+ existingKey.length === identityKey.length &&
272
+ existingKey.every((byte, i) => byte === identityKey[i]);
273
+ if (existingKey && !keysMatch) {
274
+ // Identity changed — clear stale session, save new key
275
+ if (logger) logger.info({ id }, 'identity key changed, clearing stale session');
276
+ await keys.set({
277
+ session: { [id]: null },
278
+ 'identity-key': { [id]: identityKey }
279
+ });
280
+ return true;
281
+ }
282
+ if (!existingKey) {
283
+ // New contact — TOFU
284
+ await keys.set({ 'identity-key': { [id]: identityKey } });
285
+ return true;
286
+ }
287
+ return false;
288
+ },
289
+
290
+ loadPreKey: async (id) => {
291
+ const keyId = id.toString();
292
+ const { [keyId]: key } = await keys.get('pre-key', [keyId]);
293
+ if (key) {
294
+ return {
295
+ privKey: Buffer.from(key.private),
296
+ pubKey: Buffer.from(key.public)
297
+ };
298
+ }
299
+ },
300
+
301
+ removePreKey: (id) => keys.set({ 'pre-key': { [id]: null } }),
302
+
303
+ loadSignedPreKey: () => {
304
+ const key = creds.signedPreKey;
305
+ return {
306
+ privKey: Buffer.from(key.keyPair.private),
307
+ pubKey: Buffer.from(key.keyPair.public)
308
+ };
309
+ },
310
+
311
+ loadSenderKey: async (senderKeyName) => {
312
+ const keyId = senderKeyName.toString();
313
+ const { [keyId]: key } = await keys.get('sender-key', [keyId]);
314
+ if (key) {
315
+ return sender_key_record_1.SenderKeyRecord.deserialize(key);
316
+ }
317
+ return new sender_key_record_1.SenderKeyRecord();
318
+ },
319
+
320
+ storeSenderKey: async (senderKeyName, key) => {
321
+ const keyId = senderKeyName.toString();
322
+ const serialized = JSON.stringify(key.serialize());
323
+ await keys.set({ 'sender-key': { [keyId]: Buffer.from(serialized, 'utf-8') } });
324
+ },
325
+
326
+ getOurRegistrationId: () => creds.registrationId,
327
+
328
+ getOurIdentity: () => {
329
+ const { signedIdentityKey } = creds;
330
+ return {
331
+ privKey: Buffer.from(signedIdentityKey.private),
332
+ pubKey: (0, Utils_1.generateSignalPubKey)(signedIdentityKey.public)
333
+ };
334
+ }
335
+ };
336
+ }