@gqb333/based 2.7.79 → 2.7.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Utils/crypto.js +198 -81
- package/lib/Utils/decode-wa-message.js +192 -138
- package/lib/Utils/generics.js +149 -215
- package/package.json +1 -1
|
@@ -1,207 +1,261 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
|
|
2
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
4
|
exports.decryptMessageNode = exports.NACK_REASONS = exports.MISSING_KEYS_ERROR_TEXT = exports.NO_MESSAGE_FOUND_ERROR_TEXT = void 0;
|
|
4
5
|
exports.decodeMessageNode = decodeMessageNode;
|
|
5
|
-
|
|
6
|
+
|
|
7
|
+
const boom_1 = require("@hapi/boom");
|
|
6
8
|
const WAProto_1 = require("../../WAProto");
|
|
7
9
|
const WABinary_1 = require("../WABinary");
|
|
8
10
|
const generics_1 = require("./generics");
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
9
14
|
exports.NO_MESSAGE_FOUND_ERROR_TEXT = 'Message absent from node';
|
|
10
|
-
exports.MISSING_KEYS_ERROR_TEXT
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
const senderLid = (_b = stanza === null || stanza === void 0 ? void 0 : stanza.attrs) === null || _b === void 0 ? void 0 : _b.sender_lid;
|
|
39
|
-
const participant = stanza.attrs.participant;
|
|
40
|
-
const participantLid = (_c = stanza === null || stanza === void 0 ? void 0 : stanza.attrs) === null || _c === void 0 ? void 0 : _c.participant_lid;
|
|
41
|
-
const recipient = stanza.attrs.recipient;
|
|
42
|
-
const isMe = (jid) => (0, WABinary_1.areJidsSameUser)(jid, meId);
|
|
15
|
+
exports.MISSING_KEYS_ERROR_TEXT = 'Key used already or never filled';
|
|
16
|
+
|
|
17
|
+
exports.NACK_REASONS = Object.freeze({
|
|
18
|
+
ParsingError: 487,
|
|
19
|
+
UnrecognizedStanza: 488,
|
|
20
|
+
UnrecognizedStanzaClass: 489,
|
|
21
|
+
UnrecognizedStanzaType: 490,
|
|
22
|
+
InvalidProtobuf: 491,
|
|
23
|
+
InvalidHostedCompanionStanza:493,
|
|
24
|
+
MissingMessageSecret: 495,
|
|
25
|
+
SignalErrorOldCounter: 496,
|
|
26
|
+
MessageDeletedOnPeer: 499,
|
|
27
|
+
UnhandledError: 500,
|
|
28
|
+
UnsupportedAdminRevoke: 550,
|
|
29
|
+
UnsupportedLIDGroup: 551,
|
|
30
|
+
DBOperationFailed: 552
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
function attr(stanza, key) {
|
|
37
|
+
return stanza?.attrs?.[key];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
function makeIdentityCheckers(meId, meLid) {
|
|
42
|
+
const isMe = (jid) => (0, WABinary_1.areJidsSameUser)(jid, meId);
|
|
43
43
|
const isMeLid = (jid) => (0, WABinary_1.areJidsSameUser)(jid, meLid);
|
|
44
|
+
return { isMe, isMeLid };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
function decodeMessageNode(stanza, meId, meLid) {
|
|
50
|
+
const { isMe, isMeLid } = makeIdentityCheckers(meId, meLid);
|
|
51
|
+
|
|
52
|
+
const msgId = stanza.attrs.id;
|
|
53
|
+
const from = stanza.attrs.from;
|
|
54
|
+
const participant = stanza.attrs.participant;
|
|
55
|
+
const recipient = stanza.attrs.recipient;
|
|
56
|
+
const senderPn = attr(stanza, 'sender_pn');
|
|
57
|
+
const senderLid = attr(stanza, 'sender_lid');
|
|
58
|
+
const participantLid = attr(stanza, 'participant_lid');
|
|
59
|
+
|
|
60
|
+
let msgType, chatId, author;
|
|
61
|
+
|
|
62
|
+
|
|
44
63
|
if ((0, WABinary_1.isJidUser)(from) || (0, WABinary_1.isLidUser)(from)) {
|
|
45
64
|
if (recipient && !(0, WABinary_1.isJidMetaAi)(recipient)) {
|
|
46
65
|
if (!isMe(from) && !isMeLid(from)) {
|
|
47
|
-
throw new boom_1.Boom('
|
|
66
|
+
throw new boom_1.Boom('recipient present, but msg not from me', { data: stanza });
|
|
48
67
|
}
|
|
49
68
|
chatId = recipient;
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
69
|
+
} else {
|
|
52
70
|
chatId = from;
|
|
53
71
|
}
|
|
54
72
|
msgType = 'chat';
|
|
55
|
-
author
|
|
56
|
-
|
|
57
|
-
else if ((0, WABinary_1.isJidGroup)(from)) {
|
|
58
|
-
if (!participant)
|
|
59
|
-
throw new boom_1.Boom('No participant in group message');
|
|
60
|
-
}
|
|
73
|
+
author = from;
|
|
74
|
+
|
|
75
|
+
} else if ((0, WABinary_1.isJidGroup)(from)) {
|
|
76
|
+
if (!participant) throw new boom_1.Boom('No participant in group message');
|
|
61
77
|
msgType = 'group';
|
|
62
|
-
author
|
|
63
|
-
chatId
|
|
64
|
-
|
|
65
|
-
else if ((0, WABinary_1.isJidNewsletter)(from)) {
|
|
78
|
+
author = participant;
|
|
79
|
+
chatId = from;
|
|
80
|
+
|
|
81
|
+
} else if ((0, WABinary_1.isJidNewsletter)(from)) {
|
|
66
82
|
msgType = 'newsletter';
|
|
67
|
-
author
|
|
68
|
-
chatId
|
|
69
|
-
|
|
70
|
-
else if ((0, WABinary_1.isJidBroadcast)(from)) {
|
|
71
|
-
if (!participant)
|
|
72
|
-
throw new boom_1.Boom('No participant in group message');
|
|
73
|
-
}
|
|
83
|
+
author = from;
|
|
84
|
+
chatId = from;
|
|
85
|
+
|
|
86
|
+
} else if ((0, WABinary_1.isJidBroadcast)(from)) {
|
|
87
|
+
if (!participant) throw new boom_1.Boom('No participant in broadcast message');
|
|
74
88
|
const isParticipantMe = isMe(participant);
|
|
75
89
|
if ((0, WABinary_1.isJidStatusBroadcast)(from)) {
|
|
76
90
|
msgType = isParticipantMe ? 'direct_peer_status' : 'other_status';
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
91
|
+
} else {
|
|
79
92
|
msgType = isParticipantMe ? 'peer_broadcast' : 'other_broadcast';
|
|
80
93
|
}
|
|
81
94
|
chatId = from;
|
|
82
95
|
author = participant;
|
|
83
|
-
|
|
84
|
-
else {
|
|
96
|
+
|
|
97
|
+
} else {
|
|
85
98
|
throw new boom_1.Boom('Unknown message type', { data: stanza });
|
|
86
99
|
}
|
|
87
|
-
|
|
88
|
-
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
const fromMe = (0, WABinary_1.isJidNewsletter)(from)
|
|
103
|
+
? !!(stanza.attrs?.is_sender) || false
|
|
104
|
+
: ((0, WABinary_1.isLidUser)(from) ? isMeLid : isMe)(participant || from);
|
|
105
|
+
|
|
106
|
+
|
|
89
107
|
const key = {
|
|
90
|
-
remoteJid:
|
|
108
|
+
remoteJid: chatId,
|
|
91
109
|
fromMe,
|
|
92
|
-
id:
|
|
110
|
+
id: msgId,
|
|
93
111
|
senderPn,
|
|
94
112
|
senderLid,
|
|
95
113
|
participant,
|
|
96
114
|
participantLid,
|
|
97
|
-
|
|
115
|
+
server_id: attr(stanza, 'server_id')
|
|
98
116
|
};
|
|
117
|
+
|
|
99
118
|
const fullMessage = {
|
|
100
119
|
key,
|
|
101
120
|
messageTimestamp: +stanza.attrs.t,
|
|
102
|
-
pushName:
|
|
103
|
-
broadcast:
|
|
121
|
+
pushName: attr(stanza, 'notify'),
|
|
122
|
+
broadcast: (0, WABinary_1.isJidBroadcast)(from)
|
|
104
123
|
};
|
|
124
|
+
|
|
105
125
|
if (msgType === 'newsletter') {
|
|
106
|
-
fullMessage.newsletterServerId = +((
|
|
126
|
+
fullMessage.newsletterServerId = +(attr(stanza, 'server_id'));
|
|
107
127
|
}
|
|
128
|
+
|
|
108
129
|
if (key.fromMe) {
|
|
109
130
|
fullMessage.status = WAProto_1.proto.WebMessageInfo.Status.SERVER_ACK;
|
|
110
131
|
}
|
|
132
|
+
|
|
111
133
|
return {
|
|
112
134
|
fullMessage,
|
|
113
135
|
author,
|
|
114
136
|
sender: msgType === 'chat' ? author : chatId
|
|
115
137
|
};
|
|
116
138
|
}
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
117
142
|
const decryptMessageNode = (stanza, meId, meLid, repository, logger) => {
|
|
118
143
|
const { fullMessage, author, sender } = decodeMessageNode(stanza, meId, meLid);
|
|
144
|
+
|
|
119
145
|
return {
|
|
120
146
|
fullMessage,
|
|
121
147
|
category: stanza.attrs.category,
|
|
122
148
|
author,
|
|
149
|
+
|
|
123
150
|
async decrypt() {
|
|
124
|
-
var _a;
|
|
125
151
|
let decryptables = 0;
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
if (msg.senderKeyDistributionMessage) {
|
|
175
|
-
try {
|
|
176
|
-
await repository.processSenderKeyDistributionMessage({
|
|
177
|
-
authorJid: author,
|
|
178
|
-
item: msg.senderKeyDistributionMessage
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
catch (err) {
|
|
182
|
-
logger.error({ key: fullMessage.key, err }, 'failed to decrypt message');
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
if (fullMessage.message) {
|
|
186
|
-
Object.assign(fullMessage.message, msg);
|
|
187
|
-
}
|
|
188
|
-
else {
|
|
189
|
-
fullMessage.message = msg;
|
|
152
|
+
|
|
153
|
+
if (!Array.isArray(stanza.content)) {
|
|
154
|
+
fullMessage.messageStubType = WAProto_1.proto.WebMessageInfo.StubType.CIPHERTEXT;
|
|
155
|
+
fullMessage.messageStubParameters = [exports.NO_MESSAGE_FOUND_ERROR_TEXT];
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
for (const { tag, attrs, content } of stanza.content) {
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
if (tag === 'verified_name' && content instanceof Uint8Array) {
|
|
164
|
+
const cert = WAProto_1.proto.VerifiedNameCertificate.decode(content);
|
|
165
|
+
const details = WAProto_1.proto.VerifiedNameCertificate.Details.decode(cert.details);
|
|
166
|
+
fullMessage.verifiedBizName = details.verifiedName;
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (tag === 'unavailable' && attrs.type === 'view_once') {
|
|
171
|
+
fullMessage.key.isViewOnce = true;
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if ((tag !== 'enc' && tag !== 'plaintext') || !(content instanceof Uint8Array)) {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
decryptables++;
|
|
180
|
+
|
|
181
|
+
try {
|
|
182
|
+
const msgBuffer = await decryptContent(tag, attrs, content, sender, author, repository);
|
|
183
|
+
|
|
184
|
+
let msg = WAProto_1.proto.Message.decode(
|
|
185
|
+
tag !== 'plaintext' ? (0, generics_1.unpadRandomMax16)(msgBuffer) : msgBuffer
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
// Unwrap device-sent message
|
|
189
|
+
msg = msg?.deviceSentMessage?.message || msg;
|
|
190
|
+
|
|
191
|
+
// Processa sender key distribution
|
|
192
|
+
if (msg.senderKeyDistributionMessage) {
|
|
193
|
+
try {
|
|
194
|
+
await repository.processSenderKeyDistributionMessage({
|
|
195
|
+
authorJid: author,
|
|
196
|
+
item: msg.senderKeyDistributionMessage
|
|
197
|
+
});
|
|
198
|
+
} catch (err) {
|
|
199
|
+
logger.error({ key: fullMessage.key, err }, 'failed to process senderKeyDistribution');
|
|
190
200
|
}
|
|
191
201
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
fullMessage.
|
|
202
|
+
|
|
203
|
+
// Merge nel messaggio completo
|
|
204
|
+
if (fullMessage.message) {
|
|
205
|
+
Object.assign(fullMessage.message, msg);
|
|
206
|
+
} else {
|
|
207
|
+
fullMessage.message = msg;
|
|
196
208
|
}
|
|
209
|
+
|
|
210
|
+
} catch (err) {
|
|
211
|
+
logger.error({ key: fullMessage.key, err }, 'failed to decrypt message');
|
|
212
|
+
fullMessage.messageStubType = WAProto_1.proto.WebMessageInfo.StubType.CIPHERTEXT;
|
|
213
|
+
fullMessage.messageStubParameters = [err.message];
|
|
197
214
|
}
|
|
198
215
|
}
|
|
199
|
-
|
|
216
|
+
|
|
217
|
+
// Nessun contenuto decifrable trovato
|
|
200
218
|
if (!decryptables) {
|
|
201
|
-
fullMessage.messageStubType
|
|
219
|
+
fullMessage.messageStubType = WAProto_1.proto.WebMessageInfo.StubType.CIPHERTEXT;
|
|
202
220
|
fullMessage.messageStubParameters = [exports.NO_MESSAGE_FOUND_ERROR_TEXT];
|
|
203
221
|
}
|
|
204
222
|
}
|
|
205
223
|
};
|
|
206
224
|
};
|
|
207
|
-
exports.decryptMessageNode = decryptMessageNode;
|
|
225
|
+
exports.decryptMessageNode = decryptMessageNode;
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Decifra il contenuto di un nodo enc/plaintext.
|
|
231
|
+
* Estratto per leggibilità e testabilità.
|
|
232
|
+
*/
|
|
233
|
+
async function decryptContent(tag, attrs, content, sender, author, repository) {
|
|
234
|
+
const e2eType = tag === 'plaintext' ? 'plaintext' : attrs.type;
|
|
235
|
+
|
|
236
|
+
switch (e2eType) {
|
|
237
|
+
case 'skmsg':
|
|
238
|
+
return repository.decryptGroupMessage({
|
|
239
|
+
group: sender,
|
|
240
|
+
authorJid: author,
|
|
241
|
+
msg: content
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
case 'pkmsg':
|
|
245
|
+
case 'msg': {
|
|
246
|
+
const user = (0, WABinary_1.isJidUser)(sender) ? sender : author;
|
|
247
|
+
return repository.decryptMessage({
|
|
248
|
+
jid: user,
|
|
249
|
+
type: e2eType,
|
|
250
|
+
ciphertext: content
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
case 'plaintext':
|
|
255
|
+
case undefined:
|
|
256
|
+
return content;
|
|
257
|
+
|
|
258
|
+
default:
|
|
259
|
+
throw new Error(`Tipo e2e non riconosciuto: ${e2eType}`);
|
|
260
|
+
}
|
|
261
|
+
}
|