"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.xmppSignedPreKey = exports.xmppPreKey = exports.parseAndInjectE2ESessions = exports.getPreKeys = exports.getNextPreKeysNode = exports.getNextPreKeys = exports.generateOrGetPreKeys = exports.extractDeviceJids = exports.createSignalIdentity = void 0;var _index = require("../Defaults/index.js"); var _index2 = require("../WABinary/index.js"); var _crypto = require("./crypto.js"); var _generics = require("./generics.js"); function chunk(array, size) { const chunks = []; for (let i = 0; i < array.length; i += size) { chunks.push(array.slice(i, i + size)); } return chunks; } const createSignalIdentity = (wid, accountSignatureKey) => { return { identifier: { name: wid, deviceId: 0 }, identifierKey: (0, _crypto.generateSignalPubKey)(accountSignatureKey) }; };exports.createSignalIdentity = createSignalIdentity; const getPreKeys = async ({ get }, min, limit) => { const idList = []; for (let id = min; id < limit; id++) { idList.push(id.toString()); } return get('pre-key', idList); };exports.getPreKeys = getPreKeys; const generateOrGetPreKeys = (creds, range) => { const avaliable = creds.nextPreKeyId - creds.firstUnuploadedPreKeyId; const remaining = range - avaliable; const lastPreKeyId = creds.nextPreKeyId + remaining - 1; const newPreKeys = {}; if (remaining > 0) { for (let i = creds.nextPreKeyId; i <= lastPreKeyId; i++) { newPreKeys[i] = _crypto.Curve.generateKeyPair(); } } return { newPreKeys, lastPreKeyId, preKeysRange: [creds.firstUnuploadedPreKeyId, range] }; };exports.generateOrGetPreKeys = generateOrGetPreKeys; const xmppSignedPreKey = (key) => ({ tag: 'skey', attrs: {}, content: [ { tag: 'id', attrs: {}, content: (0, _generics.encodeBigEndian)(key.keyId, 3) }, { tag: 'value', attrs: {}, content: key.keyPair.public }, { tag: 'signature', attrs: {}, content: key.signature }] });exports.xmppSignedPreKey = xmppSignedPreKey; const xmppPreKey = (pair, id) => ({ tag: 'key', attrs: {}, content: [ { tag: 'id', attrs: {}, content: (0, _generics.encodeBigEndian)(id, 3) }, { tag: 'value', attrs: {}, content: pair.public }] });exports.xmppPreKey = xmppPreKey; const parseAndInjectE2ESessions = async (node, repository) => { const extractKey = (key) => key ? { keyId: (0, _index2.getBinaryNodeChildUInt)(key, 'id', 3), publicKey: (0, _crypto.generateSignalPubKey)((0, _index2.getBinaryNodeChildBuffer)(key, 'value')), signature: (0, _index2.getBinaryNodeChildBuffer)(key, 'signature') } : undefined; const nodes = (0, _index2.getBinaryNodeChildren)((0, _index2.getBinaryNodeChild)(node, 'list'), 'user'); for (const node of nodes) { (0, _index2.assertNodeErrorFree)(node); } // Most of the work in repository.injectE2ESession is CPU intensive, not IO // So Promise.all doesn't really help here, // but blocks even loop if we're using it inside keys.transaction, and it makes it "sync" actually // This way we chunk it in smaller parts and between those parts we can yield to the event loop // It's rare case when you need to E2E sessions for so many users, but it's possible const chunkSize = 100; const chunks = chunk(nodes, chunkSize); for (const nodesChunk of chunks) { for (const node of nodesChunk) { const signedKey = (0, _index2.getBinaryNodeChild)(node, 'skey'); const key = (0, _index2.getBinaryNodeChild)(node, 'key'); const identity = (0, _index2.getBinaryNodeChildBuffer)(node, 'identity'); const jid = node.attrs.jid; const registrationId = (0, _index2.getBinaryNodeChildUInt)(node, 'registration', 4); await repository.injectE2ESession({ jid, session: { registrationId: registrationId, identityKey: (0, _crypto.generateSignalPubKey)(identity), signedPreKey: extractKey(signedKey), preKey: extractKey(key) } }); } } };exports.parseAndInjectE2ESessions = parseAndInjectE2ESessions; const extractDeviceJids = (result, myJid, myLid, excludeZeroDevices) => { const { user: myUser, device: myDevice } = (0, _index2.jidDecode)(myJid); const extracted = []; for (const userResult of result) { const { devices, id } = userResult; const decoded = (0, _index2.jidDecode)(id),{ user, server } = decoded; let { domainType } = decoded; const deviceList = devices?.deviceList; if (!Array.isArray(deviceList)) continue; for (const { id: device, keyIndex, isHosted } of deviceList) { if ((!excludeZeroDevices || device !== 0) && (// if zero devices are not-excluded, or device is non zero myUser !== user && myLid !== user || myDevice !== device) && (// either different user or if me user, not this device device === 0 || !!keyIndex) // ensure that "key-index" is specified for "non-zero" devices, produces a bad req otherwise ) { if (isHosted) { domainType = domainType === _index2.WAJIDDomains.LID ? _index2.WAJIDDomains.HOSTED_LID : _index2.WAJIDDomains.HOSTED; } extracted.push({ user, device, domainType, server: (0, _index2.getServerFromDomainType)(server, domainType) }); } } } return extracted; }; /** * get the next N keys for upload or processing * @param count number of pre-keys to get or generate */exports.extractDeviceJids = extractDeviceJids; const getNextPreKeys = async ({ creds, keys }, count) => { const { newPreKeys, lastPreKeyId, preKeysRange } = generateOrGetPreKeys(creds, count); const update = { nextPreKeyId: Math.max(lastPreKeyId + 1, creds.nextPreKeyId), firstUnuploadedPreKeyId: Math.max(creds.firstUnuploadedPreKeyId, lastPreKeyId + 1) }; await keys.set({ 'pre-key': newPreKeys }); const preKeys = await getPreKeys(keys, preKeysRange[0], preKeysRange[0] + preKeysRange[1]); return { update, preKeys }; };exports.getNextPreKeys = getNextPreKeys; const getNextPreKeysNode = async (state, count) => { const { creds } = state; const { update, preKeys } = await getNextPreKeys(state, count); const node = { tag: 'iq', attrs: { xmlns: 'encrypt', type: 'set', to: _index2.S_WHATSAPP_NET }, content: [ { tag: 'registration', attrs: {}, content: (0, _generics.encodeBigEndian)(creds.registrationId) }, { tag: 'type', attrs: {}, content: _index.KEY_BUNDLE_TYPE }, { tag: 'identity', attrs: {}, content: creds.signedIdentityKey.public }, { tag: 'list', attrs: {}, content: Object.keys(preKeys).map((k) => xmppPreKey(preKeys[+k], +k)) }, xmppSignedPreKey(creds.signedPreKey)] }; return { update, node }; };exports.getNextPreKeysNode = getNextPreKeysNode; /* v9-4199034f324dc87f */