Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MR414N-ID
GitHub Repository: MR414N-ID/botku2
Path: blob/master/node_modules/@adiwajshing/baileys/lib/Utils/legacy-msgs.js
1129 views
1
"use strict";
2
Object.defineProperty(exports, "__esModule", { value: true });
3
exports.getAuthenticationCredsType = exports.useSingleFileLegacyAuthState = exports.computeChallengeResponse = exports.validateNewConnection = exports.decodeWAMessage = exports.newLegacyAuthCreds = void 0;
4
const boom_1 = require("@hapi/boom");
5
const crypto_1 = require("crypto");
6
const Types_1 = require("../Types");
7
const WABinary_1 = require("../WABinary");
8
const crypto_2 = require("./crypto");
9
const generics_1 = require("./generics");
10
const newLegacyAuthCreds = () => ({
11
clientID: (0, crypto_1.randomBytes)(16).toString('base64')
12
});
13
exports.newLegacyAuthCreds = newLegacyAuthCreds;
14
const decodeWAMessage = (message, auth, fromMe = false) => {
15
let commaIndex = message.indexOf(','); // all whatsapp messages have a tag and a comma, followed by the actual message
16
if (commaIndex < 0) {
17
throw new boom_1.Boom('invalid message', { data: message });
18
} // if there was no comma, then this message must be not be valid
19
if (message[commaIndex + 1] === ',') {
20
commaIndex += 1;
21
}
22
let data = message.slice(commaIndex + 1, message.length);
23
// get the message tag.
24
// If a query was done, the server will respond with the same message tag we sent the query with
25
const messageTag = message.slice(0, commaIndex).toString();
26
let json;
27
let tags;
28
if (data.length) {
29
const possiblyEnc = (data.length > 32 && data.length % 16 === 0);
30
if (typeof data === 'string' || !possiblyEnc) {
31
json = JSON.parse(data.toString()); // parse the JSON
32
}
33
else {
34
try {
35
json = JSON.parse(data.toString());
36
}
37
catch (_a) {
38
const { macKey, encKey } = auth || {};
39
if (!macKey || !encKey) {
40
throw new boom_1.Boom('recieved encrypted buffer when auth creds unavailable', { data: message, statusCode: Types_1.DisconnectReason.badSession });
41
}
42
/*
43
If the data recieved was not a JSON, then it must be an encrypted message.
44
Such a message can only be decrypted if we're connected successfully to the servers & have encryption keys
45
*/
46
if (fromMe) {
47
tags = [data[0], data[1]];
48
data = data.slice(2, data.length);
49
}
50
const checksum = data.slice(0, 32); // the first 32 bytes of the buffer are the HMAC sign of the message
51
data = data.slice(32, data.length); // the actual message
52
const computedChecksum = (0, crypto_2.hmacSign)(data, macKey); // compute the sign of the message we recieved using our macKey
53
if (checksum.equals(computedChecksum)) {
54
// the checksum the server sent, must match the one we computed for the message to be valid
55
const decrypted = (0, crypto_2.aesDecrypt)(data, encKey); // decrypt using AES
56
json = (0, WABinary_1.decodeBinaryNodeLegacy)(decrypted, { index: 0 }); // decode the binary message into a JSON array
57
}
58
else {
59
throw new boom_1.Boom('Bad checksum', {
60
data: {
61
received: checksum.toString('hex'),
62
computed: computedChecksum.toString('hex'),
63
data: data.slice(0, 80).toString(),
64
tag: messageTag,
65
message: message.slice(0, 80).toString()
66
},
67
statusCode: Types_1.DisconnectReason.badSession
68
});
69
}
70
}
71
}
72
}
73
return [messageTag, json, tags];
74
};
75
exports.decodeWAMessage = decodeWAMessage;
76
/**
77
* Once the QR code is scanned and we can validate our connection, or we resolved the challenge when logging back in
78
* @private
79
* @param json
80
*/
81
const validateNewConnection = (json, auth, curveKeys) => {
82
// set metadata: one's WhatsApp ID [cc][number]@s.whatsapp.net, name on WhatsApp, info about the phone
83
const onValidationSuccess = () => {
84
const user = {
85
id: (0, WABinary_1.jidNormalizedUser)(json.wid),
86
name: json.pushname
87
};
88
return { user, auth, phone: json.phone };
89
};
90
if (!json.secret) {
91
// if we didn't get a secret, we don't need it, we're validated
92
if (json.clientToken && json.clientToken !== auth.clientToken) {
93
auth = { ...auth, clientToken: json.clientToken };
94
}
95
if (json.serverToken && json.serverToken !== auth.serverToken) {
96
auth = { ...auth, serverToken: json.serverToken };
97
}
98
return onValidationSuccess();
99
}
100
const secret = Buffer.from(json.secret, 'base64');
101
if (secret.length !== 144) {
102
throw new Error('incorrect secret length received: ' + secret.length);
103
}
104
// generate shared key from our private key & the secret shared by the server
105
const sharedKey = crypto_2.Curve.sharedKey(curveKeys.private, secret.slice(0, 32));
106
// expand the key to 80 bytes using HKDF
107
const expandedKey = (0, crypto_2.hkdf)(sharedKey, 80, {});
108
// perform HMAC validation.
109
const hmacValidationKey = expandedKey.slice(32, 64);
110
const hmacValidationMessage = Buffer.concat([secret.slice(0, 32), secret.slice(64, secret.length)]);
111
const hmac = (0, crypto_2.hmacSign)(hmacValidationMessage, hmacValidationKey);
112
if (!hmac.equals(secret.slice(32, 64))) {
113
// if the checksums didn't match
114
throw new boom_1.Boom('HMAC validation failed', { statusCode: 400 });
115
}
116
// computed HMAC should equal secret[32:64]
117
// expandedKey[64:] + secret[64:] are the keys, encrypted using AES, that are used to encrypt/decrypt the messages recieved from WhatsApp
118
// they are encrypted using key: expandedKey[0:32]
119
const encryptedAESKeys = Buffer.concat([
120
expandedKey.slice(64, expandedKey.length),
121
secret.slice(64, secret.length),
122
]);
123
const decryptedKeys = (0, crypto_2.aesDecrypt)(encryptedAESKeys, expandedKey.slice(0, 32));
124
// set the credentials
125
auth = {
126
encKey: decryptedKeys.slice(0, 32),
127
macKey: decryptedKeys.slice(32, 64),
128
clientToken: json.clientToken,
129
serverToken: json.serverToken,
130
clientID: auth.clientID,
131
};
132
return onValidationSuccess();
133
};
134
exports.validateNewConnection = validateNewConnection;
135
const computeChallengeResponse = (challenge, auth) => {
136
const bytes = Buffer.from(challenge, 'base64'); // decode the base64 encoded challenge string
137
const signed = (0, crypto_2.hmacSign)(bytes, auth.macKey).toString('base64'); // sign the challenge string with our macKey
138
return ['admin', 'challenge', signed, auth.serverToken, auth.clientID]; // prepare to send this signed string with the serverToken & clientID
139
};
140
exports.computeChallengeResponse = computeChallengeResponse;
141
const useSingleFileLegacyAuthState = (file) => {
142
// require fs here so that in case "fs" is not available -- the app does not crash
143
const { readFileSync, writeFileSync, existsSync } = require('fs');
144
let state;
145
if (existsSync(file)) {
146
state = JSON.parse(readFileSync(file, { encoding: 'utf-8' }), generics_1.BufferJSON.reviver);
147
if (typeof state.encKey === 'string') {
148
state.encKey = Buffer.from(state.encKey, 'base64');
149
}
150
if (typeof state.macKey === 'string') {
151
state.macKey = Buffer.from(state.macKey, 'base64');
152
}
153
}
154
else {
155
state = (0, exports.newLegacyAuthCreds)();
156
}
157
return {
158
state,
159
saveState: () => {
160
const str = JSON.stringify(state, generics_1.BufferJSON.replacer, 2);
161
writeFileSync(file, str);
162
}
163
};
164
};
165
exports.useSingleFileLegacyAuthState = useSingleFileLegacyAuthState;
166
const getAuthenticationCredsType = (creds) => {
167
if ('clientID' in creds && !!creds.clientID) {
168
return 'legacy';
169
}
170
if ('noiseKey' in creds && !!creds.noiseKey) {
171
return 'md';
172
}
173
};
174
exports.getAuthenticationCredsType = getAuthenticationCredsType;
175
176