violetics 7.0.1-alpha → 7.0.2-alpha
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/LICENSE +3 -2
- package/README.md +1001 -232
- package/WAProto/index.js +75379 -142631
- package/engine-requirements.js +11 -8
- package/lib/Defaults/index.js +132 -146
- package/lib/Signal/Group/ciphertext-message.js +2 -6
- package/lib/Signal/Group/group-session-builder.js +7 -42
- package/lib/Signal/Group/group_cipher.js +37 -52
- package/lib/Signal/Group/index.js +11 -57
- package/lib/Signal/Group/keyhelper.js +7 -45
- package/lib/Signal/Group/sender-chain-key.js +7 -16
- package/lib/Signal/Group/sender-key-distribution-message.js +8 -12
- package/lib/Signal/Group/sender-key-message.js +9 -13
- package/lib/Signal/Group/sender-key-name.js +2 -6
- package/lib/Signal/Group/sender-key-record.js +9 -22
- package/lib/Signal/Group/sender-key-state.js +27 -43
- package/lib/Signal/Group/sender-message-key.js +4 -8
- package/lib/Signal/libsignal.js +319 -94
- package/lib/Signal/lid-mapping.js +224 -139
- package/lib/Socket/Client/index.js +2 -19
- package/lib/Socket/Client/types.js +10 -0
- package/lib/Socket/Client/websocket.js +53 -0
- package/lib/Socket/business.js +162 -44
- package/lib/Socket/chats.js +477 -418
- package/lib/Socket/communities.js +430 -0
- package/lib/Socket/groups.js +110 -99
- package/lib/Socket/index.js +10 -10
- package/lib/Socket/messages-recv.js +884 -561
- package/lib/Socket/messages-send.js +859 -428
- package/lib/Socket/mex.js +41 -0
- package/lib/Socket/newsletter.js +195 -390
- package/lib/Socket/socket.js +465 -315
- package/lib/Store/index.js +3 -10
- package/lib/Store/make-in-memory-store.js +73 -79
- package/lib/Store/make-ordered-dictionary.js +4 -7
- package/lib/Store/object-repository.js +2 -6
- package/lib/Types/Auth.js +1 -2
- package/lib/Types/Bussines.js +1 -0
- package/lib/Types/Call.js +1 -2
- package/lib/Types/Chat.js +7 -4
- package/lib/Types/Contact.js +1 -2
- package/lib/Types/Events.js +1 -2
- package/lib/Types/GroupMetadata.js +1 -2
- package/lib/Types/Label.js +2 -5
- package/lib/Types/LabelAssociation.js +2 -5
- package/lib/Types/Message.js +17 -9
- package/lib/Types/Newsletter.js +33 -38
- package/lib/Types/Product.js +1 -2
- package/lib/Types/Signal.js +1 -2
- package/lib/Types/Socket.js +2 -2
- package/lib/Types/State.js +12 -2
- package/lib/Types/USync.js +1 -2
- package/lib/Types/index.js +14 -31
- package/lib/Utils/auth-utils.js +228 -152
- package/lib/Utils/browser-utils.js +28 -0
- package/lib/Utils/business.js +66 -70
- package/lib/Utils/chat-utils.js +331 -249
- package/lib/Utils/crypto.js +57 -91
- package/lib/Utils/decode-wa-message.js +168 -84
- package/lib/Utils/event-buffer.js +138 -80
- package/lib/Utils/generics.js +180 -297
- package/lib/Utils/history.js +83 -49
- package/lib/Utils/identity-change-handler.js +48 -0
- package/lib/Utils/index.js +19 -33
- package/lib/Utils/link-preview.js +14 -23
- package/lib/Utils/logger.js +2 -7
- package/lib/Utils/lt-hash.js +2 -46
- package/lib/Utils/make-mutex.js +24 -47
- package/lib/Utils/message-retry-manager.js +224 -0
- package/lib/Utils/messages-media.js +501 -496
- package/lib/Utils/messages.js +1428 -362
- package/lib/Utils/noise-handler.js +145 -100
- package/lib/Utils/pre-key-manager.js +105 -0
- package/lib/Utils/process-message.js +356 -150
- package/lib/Utils/reporting-utils.js +257 -0
- package/lib/Utils/signal.js +78 -73
- package/lib/Utils/sync-action-utils.js +47 -0
- package/lib/Utils/tc-token-utils.js +17 -0
- package/lib/Utils/use-multi-file-auth-state.js +35 -45
- package/lib/Utils/validate-connection.js +91 -107
- package/lib/WABinary/constants.js +1300 -1304
- package/lib/WABinary/decode.js +26 -48
- package/lib/WABinary/encode.js +109 -155
- package/lib/WABinary/generic-utils.js +161 -149
- package/lib/WABinary/index.js +5 -21
- package/lib/WABinary/jid-utils.js +73 -40
- package/lib/WABinary/types.js +1 -2
- package/lib/WAM/BinaryInfo.js +2 -6
- package/lib/WAM/constants.js +19070 -11568
- package/lib/WAM/encode.js +17 -23
- package/lib/WAM/index.js +3 -19
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +8 -12
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +11 -15
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +9 -13
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +9 -14
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +20 -23
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +13 -9
- package/lib/WAUSync/Protocols/index.js +4 -20
- package/lib/WAUSync/USyncQuery.js +40 -36
- package/lib/WAUSync/USyncUser.js +2 -6
- package/lib/WAUSync/index.js +3 -19
- package/lib/index.js +11 -44
- package/package.json +74 -107
- package/lib/Defaults/baileys-version.json +0 -3
- package/lib/Defaults/phonenumber-mcc.json +0 -223
- package/lib/Signal/Group/queue-job.js +0 -57
- package/lib/Socket/Client/abstract-socket-client.js +0 -13
- package/lib/Socket/Client/mobile-socket-client.js +0 -65
- package/lib/Socket/Client/web-socket-client.js +0 -118
- package/lib/Socket/groupStatus.js +0 -637
- package/lib/Socket/registration.js +0 -166
- package/lib/Socket/usync.js +0 -70
- package/lib/Store/make-cache-manager-store.js +0 -83
- package/lib/Utils/baileys-event-stream.js +0 -63
|
@@ -1,27 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { Mutex } from 'async-mutex';
|
|
2
|
+
import { mkdir, readFile, stat, unlink, writeFile } from 'fs/promises';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { proto } from '../../WAProto/index.js';
|
|
5
|
+
import { initAuthCreds } from './auth-utils.js';
|
|
6
|
+
import { BufferJSON } from './generics.js';
|
|
7
|
+
// We need to lock files due to the fact that we are using async functions to read and write files
|
|
8
|
+
// https://github.com/WhiskeySockets/Baileys/issues/794
|
|
9
|
+
// https://github.com/nodejs/node/issues/26338
|
|
10
|
+
// Use a Map to store mutexes for each file path
|
|
10
11
|
const fileLocks = new Map();
|
|
11
|
-
|
|
12
|
-
// Clean up the mutex entry when it's been garbage-collected so the
|
|
13
|
-
// Map doesn't grow unboundedly when running hundreds of bot sessions.
|
|
14
|
-
fileLocks.delete(path);
|
|
15
|
-
});
|
|
12
|
+
// Get or create a mutex for a specific file path
|
|
16
13
|
const getFileLock = (path) => {
|
|
17
|
-
let
|
|
18
|
-
if (
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
let mutex = fileLocks.get(path);
|
|
15
|
+
if (!mutex) {
|
|
16
|
+
mutex = new Mutex();
|
|
17
|
+
fileLocks.set(path, mutex);
|
|
21
18
|
}
|
|
22
|
-
const mutex = new async_mutex_1.Mutex();
|
|
23
|
-
fileLocks.set(path, new WeakRef(mutex));
|
|
24
|
-
fileLockRegistry.register(mutex, path);
|
|
25
19
|
return mutex;
|
|
26
20
|
};
|
|
27
21
|
/**
|
|
@@ -31,16 +25,14 @@ const getFileLock = (path) => {
|
|
|
31
25
|
* Again, I wouldn't endorse this for any production level use other than perhaps a bot.
|
|
32
26
|
* Would recommend writing an auth state for use with a proper SQL or No-SQL DB
|
|
33
27
|
* */
|
|
34
|
-
const useMultiFileAuthState = async (folder) => {
|
|
28
|
+
export const useMultiFileAuthState = async (folder) => {
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
35
30
|
const writeData = async (data, file) => {
|
|
36
|
-
const filePath =
|
|
37
|
-
const tmpPath = filePath + '.tmp';
|
|
31
|
+
const filePath = join(folder, fixFileName(file));
|
|
38
32
|
const mutex = getFileLock(filePath);
|
|
39
33
|
return mutex.acquire().then(async (release) => {
|
|
40
34
|
try {
|
|
41
|
-
|
|
42
|
-
await (0, promises_1.writeFile)(tmpPath, JSON.stringify(data, generics_1.BufferJSON.replacer));
|
|
43
|
-
await (0, promises_1.rename)(tmpPath, filePath);
|
|
35
|
+
await writeFile(filePath, JSON.stringify(data, BufferJSON.replacer));
|
|
44
36
|
}
|
|
45
37
|
finally {
|
|
46
38
|
release();
|
|
@@ -49,12 +41,12 @@ const useMultiFileAuthState = async (folder) => {
|
|
|
49
41
|
};
|
|
50
42
|
const readData = async (file) => {
|
|
51
43
|
try {
|
|
52
|
-
const filePath =
|
|
44
|
+
const filePath = join(folder, fixFileName(file));
|
|
53
45
|
const mutex = getFileLock(filePath);
|
|
54
46
|
return await mutex.acquire().then(async (release) => {
|
|
55
47
|
try {
|
|
56
|
-
const data = await
|
|
57
|
-
return JSON.parse(data,
|
|
48
|
+
const data = await readFile(filePath, { encoding: 'utf-8' });
|
|
49
|
+
return JSON.parse(data, BufferJSON.reviver);
|
|
58
50
|
}
|
|
59
51
|
finally {
|
|
60
52
|
release();
|
|
@@ -67,34 +59,32 @@ const useMultiFileAuthState = async (folder) => {
|
|
|
67
59
|
};
|
|
68
60
|
const removeData = async (file) => {
|
|
69
61
|
try {
|
|
70
|
-
const filePath =
|
|
62
|
+
const filePath = join(folder, fixFileName(file));
|
|
71
63
|
const mutex = getFileLock(filePath);
|
|
72
64
|
return mutex.acquire().then(async (release) => {
|
|
73
65
|
try {
|
|
74
|
-
await
|
|
66
|
+
await unlink(filePath);
|
|
75
67
|
}
|
|
76
|
-
catch
|
|
68
|
+
catch {
|
|
77
69
|
}
|
|
78
70
|
finally {
|
|
79
71
|
release();
|
|
80
72
|
}
|
|
81
73
|
});
|
|
82
74
|
}
|
|
83
|
-
catch
|
|
84
|
-
}
|
|
75
|
+
catch { }
|
|
85
76
|
};
|
|
86
|
-
const folderInfo = await
|
|
77
|
+
const folderInfo = await stat(folder).catch(() => { });
|
|
87
78
|
if (folderInfo) {
|
|
88
79
|
if (!folderInfo.isDirectory()) {
|
|
89
80
|
throw new Error(`found something that is not a directory at ${folder}, either delete it or specify a different location`);
|
|
90
81
|
}
|
|
91
82
|
}
|
|
92
83
|
else {
|
|
93
|
-
await
|
|
84
|
+
await mkdir(folder, { recursive: true });
|
|
94
85
|
}
|
|
95
|
-
const fixFileName = (file) =>
|
|
96
|
-
const creds = await readData('creds.json') ||
|
|
97
|
-
|
|
86
|
+
const fixFileName = (file) => file?.replace(/\//g, '__')?.replace(/:/g, '-');
|
|
87
|
+
const creds = (await readData('creds.json')) || initAuthCreds();
|
|
98
88
|
return {
|
|
99
89
|
state: {
|
|
100
90
|
creds,
|
|
@@ -104,7 +94,7 @@ const useMultiFileAuthState = async (folder) => {
|
|
|
104
94
|
await Promise.all(ids.map(async (id) => {
|
|
105
95
|
let value = await readData(`${type}-${id}.json`);
|
|
106
96
|
if (type === 'app-state-sync-key' && value) {
|
|
107
|
-
value =
|
|
97
|
+
value = proto.Message.AppStateSyncKeyData.fromObject(value);
|
|
108
98
|
}
|
|
109
99
|
data[id] = value;
|
|
110
100
|
}));
|
|
@@ -123,8 +113,8 @@ const useMultiFileAuthState = async (folder) => {
|
|
|
123
113
|
}
|
|
124
114
|
}
|
|
125
115
|
},
|
|
126
|
-
|
|
127
|
-
|
|
116
|
+
saveCreds: async () => {
|
|
117
|
+
return writeData(creds, 'creds.json');
|
|
118
|
+
}
|
|
128
119
|
};
|
|
129
|
-
};
|
|
130
|
-
exports.useMultiFileAuthState = useMultiFileAuthState;
|
|
120
|
+
};
|
|
@@ -1,94 +1,102 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const crypto_2 = require("./crypto");
|
|
10
|
-
const generics_1 = require("./generics");
|
|
11
|
-
const signal_1 = require("./signal");
|
|
12
|
-
|
|
1
|
+
import { Boom } from '@hapi/boom';
|
|
2
|
+
import { createHash } from 'crypto';
|
|
3
|
+
import { proto } from '../../WAProto/index.js';
|
|
4
|
+
import { KEY_BUNDLE_TYPE, WA_ADV_ACCOUNT_SIG_PREFIX, WA_ADV_DEVICE_SIG_PREFIX, WA_ADV_HOSTED_ACCOUNT_SIG_PREFIX } from '../Defaults/index.js';
|
|
5
|
+
import { getBinaryNodeChild, jidDecode, S_WHATSAPP_NET } from '../WABinary/index.js';
|
|
6
|
+
import { Curve, hmacSign } from './crypto.js';
|
|
7
|
+
import { encodeBigEndian } from './generics.js';
|
|
8
|
+
import { createSignalIdentity } from './signal.js';
|
|
13
9
|
const getUserAgent = (config) => {
|
|
14
10
|
return {
|
|
15
11
|
appVersion: {
|
|
16
12
|
primary: config.version[0],
|
|
17
13
|
secondary: config.version[1],
|
|
18
|
-
tertiary: config.version[2]
|
|
14
|
+
tertiary: config.version[2]
|
|
19
15
|
},
|
|
20
|
-
platform:
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
platform: config.browser[1].toLocaleLowerCase().includes('android')
|
|
17
|
+
? proto.ClientPayload.UserAgent.Platform.ANDROID
|
|
18
|
+
: proto.ClientPayload.UserAgent.Platform.WEB,
|
|
19
|
+
releaseChannel: proto.ClientPayload.UserAgent.ReleaseChannel.RELEASE,
|
|
20
|
+
osVersion: '0.1',
|
|
23
21
|
device: 'Desktop',
|
|
24
|
-
osBuildNumber: '
|
|
22
|
+
osBuildNumber: '0.1',
|
|
25
23
|
localeLanguageIso6391: 'en',
|
|
26
|
-
|
|
24
|
+
mnc: '000',
|
|
25
|
+
mcc: '000',
|
|
26
|
+
localeCountryIso31661Alpha2: config.countryCode
|
|
27
27
|
};
|
|
28
28
|
};
|
|
29
|
-
|
|
30
29
|
const PLATFORM_MAP = {
|
|
31
|
-
'Mac OS':
|
|
32
|
-
|
|
30
|
+
'Mac OS': proto.ClientPayload.WebInfo.WebSubPlatform.DARWIN,
|
|
31
|
+
Windows: proto.ClientPayload.WebInfo.WebSubPlatform.WIN32
|
|
33
32
|
};
|
|
34
|
-
|
|
35
33
|
const getWebInfo = (config) => {
|
|
36
|
-
let webSubPlatform =
|
|
37
|
-
if (config.syncFullHistory &&
|
|
34
|
+
let webSubPlatform = proto.ClientPayload.WebInfo.WebSubPlatform.WEB_BROWSER;
|
|
35
|
+
if (config.syncFullHistory &&
|
|
36
|
+
PLATFORM_MAP[config.browser[0]] &&
|
|
37
|
+
config.browser[1] === 'Desktop') {
|
|
38
38
|
webSubPlatform = PLATFORM_MAP[config.browser[0]];
|
|
39
39
|
}
|
|
40
40
|
return { webSubPlatform };
|
|
41
41
|
};
|
|
42
|
-
|
|
43
42
|
const getClientPayload = (config) => {
|
|
44
43
|
const payload = {
|
|
45
|
-
connectType:
|
|
46
|
-
connectReason:
|
|
47
|
-
userAgent: getUserAgent(config)
|
|
44
|
+
connectType: proto.ClientPayload.ConnectType.WIFI_UNKNOWN,
|
|
45
|
+
connectReason: proto.ClientPayload.ConnectReason.USER_ACTIVATED,
|
|
46
|
+
userAgent: getUserAgent(config)
|
|
48
47
|
};
|
|
49
|
-
|
|
48
|
+
if (!config.browser[1].toLocaleLowerCase().includes('android')) {
|
|
49
|
+
payload.webInfo = getWebInfo(config);
|
|
50
|
+
}
|
|
50
51
|
return payload;
|
|
51
52
|
};
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
const { user, device } = (0, WABinary_1.jidDecode)(userJid);
|
|
53
|
+
export const generateLoginNode = (userJid, config) => {
|
|
54
|
+
const { user, device } = jidDecode(userJid);
|
|
55
55
|
const payload = {
|
|
56
56
|
...getClientPayload(config),
|
|
57
57
|
passive: true,
|
|
58
58
|
pull: true,
|
|
59
59
|
username: +user,
|
|
60
60
|
device: device,
|
|
61
|
+
// TODO: investigate (hard set as false atm)
|
|
61
62
|
lidDbMigrated: false
|
|
62
63
|
};
|
|
63
|
-
return
|
|
64
|
+
return proto.ClientPayload.fromObject(payload);
|
|
64
65
|
};
|
|
65
|
-
exports.generateLoginNode = generateLoginNode;
|
|
66
|
-
|
|
67
66
|
const getPlatformType = (platform) => {
|
|
68
67
|
const platformType = platform.toUpperCase();
|
|
69
|
-
|
|
68
|
+
if (platformType === 'ANDROID') {
|
|
69
|
+
return proto.DeviceProps.PlatformType.ANDROID_PHONE;
|
|
70
|
+
}
|
|
71
|
+
return (proto.DeviceProps.PlatformType[platformType] ||
|
|
72
|
+
proto.DeviceProps.PlatformType.CHROME);
|
|
70
73
|
};
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
export const generateRegistrationNode = ({ registrationId, signedPreKey, signedIdentityKey }, config) => {
|
|
75
|
+
// the app version needs to be md5 hashed
|
|
76
|
+
// and passed in
|
|
77
|
+
const appVersionBuf = createHash('md5')
|
|
78
|
+
.update(config.version.join('.')) // join as string
|
|
75
79
|
.digest();
|
|
76
|
-
|
|
77
80
|
const companion = {
|
|
78
81
|
os: config.browser[0],
|
|
79
82
|
platformType: getPlatformType(config.browser[1]),
|
|
80
83
|
requireFullSync: config.syncFullHistory,
|
|
81
84
|
historySyncConfig: {
|
|
82
85
|
storageQuotaMb: 10240,
|
|
83
|
-
inlineInitialPayloadInE2EeMsg:
|
|
84
|
-
|
|
86
|
+
inlineInitialPayloadInE2EeMsg: true,
|
|
87
|
+
recentSyncDaysLimit: undefined,
|
|
88
|
+
supportCallLogHistory: false,
|
|
89
|
+
supportBotUserAgentChatHistory: true,
|
|
85
90
|
supportCagReactionsAndPolls: true,
|
|
86
91
|
supportBizHostedMsg: true,
|
|
87
92
|
supportRecentSyncChunkMessageCountTuning: true,
|
|
88
93
|
supportHostedGroupMsg: true,
|
|
89
|
-
supportFbidBotChatHistory:
|
|
94
|
+
supportFbidBotChatHistory: true,
|
|
95
|
+
supportAddOnHistorySyncMigration: undefined,
|
|
90
96
|
supportMessageAssociation: true,
|
|
91
|
-
supportGroupHistory:
|
|
97
|
+
supportGroupHistory: false,
|
|
98
|
+
onDemandReady: undefined,
|
|
99
|
+
supportGuestChat: undefined
|
|
92
100
|
},
|
|
93
101
|
version: {
|
|
94
102
|
primary: 10,
|
|
@@ -96,9 +104,7 @@ const generateRegistrationNode = ({ registrationId, signedPreKey, signedIdentity
|
|
|
96
104
|
tertiary: 7
|
|
97
105
|
}
|
|
98
106
|
};
|
|
99
|
-
|
|
100
|
-
const companionProto = WAProto_1.proto.DeviceProps.encode(companion).finish();
|
|
101
|
-
|
|
107
|
+
const companionProto = proto.DeviceProps.encode(companion).finish();
|
|
102
108
|
const registerPayload = {
|
|
103
109
|
...getClientPayload(config),
|
|
104
110
|
passive: false,
|
|
@@ -106,77 +112,63 @@ const generateRegistrationNode = ({ registrationId, signedPreKey, signedIdentity
|
|
|
106
112
|
devicePairingData: {
|
|
107
113
|
buildHash: appVersionBuf,
|
|
108
114
|
deviceProps: companionProto,
|
|
109
|
-
eRegid:
|
|
110
|
-
eKeytype:
|
|
115
|
+
eRegid: encodeBigEndian(registrationId),
|
|
116
|
+
eKeytype: KEY_BUNDLE_TYPE,
|
|
111
117
|
eIdent: signedIdentityKey.public,
|
|
112
|
-
eSkeyId:
|
|
118
|
+
eSkeyId: encodeBigEndian(signedPreKey.keyId, 3),
|
|
113
119
|
eSkeyVal: signedPreKey.keyPair.public,
|
|
114
|
-
eSkeySig: signedPreKey.signature
|
|
115
|
-
}
|
|
120
|
+
eSkeySig: signedPreKey.signature
|
|
121
|
+
}
|
|
116
122
|
};
|
|
117
|
-
return
|
|
123
|
+
return proto.ClientPayload.fromObject(registerPayload);
|
|
118
124
|
};
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const configureSuccessfulPairing = (stanza, { advSecretKey, signedIdentityKey, signalIdentities }) => {
|
|
125
|
+
export const configureSuccessfulPairing = (stanza, { advSecretKey, signedIdentityKey, signalIdentities }) => {
|
|
122
126
|
const msgId = stanza.attrs.id;
|
|
123
|
-
const pairSuccessNode =
|
|
124
|
-
const deviceIdentityNode =
|
|
125
|
-
const platformNode =
|
|
126
|
-
const deviceNode =
|
|
127
|
-
const businessNode =
|
|
128
|
-
|
|
127
|
+
const pairSuccessNode = getBinaryNodeChild(stanza, 'pair-success');
|
|
128
|
+
const deviceIdentityNode = getBinaryNodeChild(pairSuccessNode, 'device-identity');
|
|
129
|
+
const platformNode = getBinaryNodeChild(pairSuccessNode, 'platform');
|
|
130
|
+
const deviceNode = getBinaryNodeChild(pairSuccessNode, 'device');
|
|
131
|
+
const businessNode = getBinaryNodeChild(pairSuccessNode, 'biz');
|
|
129
132
|
if (!deviceIdentityNode || !deviceNode) {
|
|
130
|
-
throw new
|
|
133
|
+
throw new Boom('Missing device-identity or device in pair success node', { data: stanza });
|
|
131
134
|
}
|
|
132
|
-
|
|
133
135
|
const bizName = businessNode?.attrs.name;
|
|
134
136
|
const jid = deviceNode.attrs.jid;
|
|
135
137
|
const lid = deviceNode.attrs.lid;
|
|
136
|
-
|
|
137
|
-
const { details, hmac, accountType } = WAProto_1.proto.ADVSignedDeviceIdentityHMAC.decode(deviceIdentityNode.content);
|
|
138
|
-
|
|
138
|
+
const { details, hmac, accountType } = proto.ADVSignedDeviceIdentityHMAC.decode(deviceIdentityNode.content);
|
|
139
139
|
let hmacPrefix = Buffer.from([]);
|
|
140
|
-
if (accountType !== undefined && accountType ===
|
|
141
|
-
hmacPrefix =
|
|
140
|
+
if (accountType !== undefined && accountType === proto.ADVEncryptionType.HOSTED) {
|
|
141
|
+
hmacPrefix = WA_ADV_HOSTED_ACCOUNT_SIG_PREFIX;
|
|
142
142
|
}
|
|
143
|
-
|
|
144
|
-
const advSign = (0, crypto_2.hmacSign)(Buffer.concat([hmacPrefix, details]), Buffer.from(advSecretKey, 'base64'));
|
|
143
|
+
const advSign = hmacSign(Buffer.concat([hmacPrefix, details]), Buffer.from(advSecretKey, 'base64'));
|
|
145
144
|
if (Buffer.compare(hmac, advSign) !== 0) {
|
|
146
|
-
throw new
|
|
145
|
+
throw new Boom('Invalid account signature');
|
|
147
146
|
}
|
|
148
|
-
|
|
149
|
-
const account = WAProto_1.proto.ADVSignedDeviceIdentity.decode(details);
|
|
147
|
+
const account = proto.ADVSignedDeviceIdentity.decode(details);
|
|
150
148
|
const { accountSignatureKey, accountSignature, details: deviceDetails } = account;
|
|
151
|
-
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
? Buffer.from([0x06, 0x05])
|
|
156
|
-
: Buffer.from([0x06, 0x00]);
|
|
149
|
+
const deviceIdentity = proto.ADVDeviceIdentity.decode(deviceDetails);
|
|
150
|
+
const accountSignaturePrefix = deviceIdentity.deviceType === proto.ADVEncryptionType.HOSTED
|
|
151
|
+
? WA_ADV_HOSTED_ACCOUNT_SIG_PREFIX
|
|
152
|
+
: WA_ADV_ACCOUNT_SIG_PREFIX;
|
|
157
153
|
const accountMsg = Buffer.concat([accountSignaturePrefix, deviceDetails, signedIdentityKey.public]);
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
throw new boom_1.Boom('Failed to verify account signature');
|
|
154
|
+
if (!Curve.verify(accountSignatureKey, accountMsg, accountSignature)) {
|
|
155
|
+
throw new Boom('Failed to verify account signature');
|
|
161
156
|
}
|
|
162
|
-
|
|
163
157
|
const deviceMsg = Buffer.concat([
|
|
164
|
-
|
|
158
|
+
WA_ADV_DEVICE_SIG_PREFIX,
|
|
165
159
|
deviceDetails,
|
|
166
160
|
signedIdentityKey.public,
|
|
167
161
|
accountSignatureKey
|
|
168
162
|
]);
|
|
169
|
-
account.deviceSignature =
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
const accountEnc = (0, exports.encodeSignedDeviceIdentity)(account, false);
|
|
173
|
-
|
|
163
|
+
account.deviceSignature = Curve.sign(signedIdentityKey.private, deviceMsg);
|
|
164
|
+
const identity = createSignalIdentity(lid, accountSignatureKey);
|
|
165
|
+
const accountEnc = encodeSignedDeviceIdentity(account, false);
|
|
174
166
|
const reply = {
|
|
175
167
|
tag: 'iq',
|
|
176
168
|
attrs: {
|
|
177
|
-
to:
|
|
169
|
+
to: S_WHATSAPP_NET,
|
|
178
170
|
type: 'result',
|
|
179
|
-
id: msgId
|
|
171
|
+
id: msgId
|
|
180
172
|
},
|
|
181
173
|
content: [
|
|
182
174
|
{
|
|
@@ -192,31 +184,23 @@ const configureSuccessfulPairing = (stanza, { advSecretKey, signedIdentityKey, s
|
|
|
192
184
|
}
|
|
193
185
|
]
|
|
194
186
|
};
|
|
195
|
-
|
|
196
187
|
const authUpdate = {
|
|
197
188
|
account,
|
|
198
189
|
me: { id: jid, name: bizName, lid },
|
|
199
|
-
signalIdentities: [
|
|
200
|
-
...(signalIdentities || []),
|
|
201
|
-
identity
|
|
202
|
-
],
|
|
190
|
+
signalIdentities: [...(signalIdentities || []), identity],
|
|
203
191
|
platform: platformNode?.attrs.name
|
|
204
192
|
};
|
|
205
|
-
|
|
206
193
|
return {
|
|
207
194
|
creds: authUpdate,
|
|
208
195
|
reply
|
|
209
196
|
};
|
|
210
197
|
};
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const encodeSignedDeviceIdentity = (account, includeSignatureKey) => {
|
|
198
|
+
export const encodeSignedDeviceIdentity = (account, includeSignatureKey) => {
|
|
214
199
|
account = { ...account };
|
|
200
|
+
// set to null if we are not to include the signature key
|
|
201
|
+
// or if we are including the signature key but it is empty
|
|
215
202
|
if (!includeSignatureKey || !account.accountSignatureKey?.length) {
|
|
216
203
|
account.accountSignatureKey = null;
|
|
217
204
|
}
|
|
218
|
-
return
|
|
219
|
-
|
|
220
|
-
.finish();
|
|
221
|
-
};
|
|
222
|
-
exports.encodeSignedDeviceIdentity = encodeSignedDeviceIdentity;
|
|
205
|
+
return proto.ADVSignedDeviceIdentity.encode(account).finish();
|
|
206
|
+
};
|