Path: blob/master/node_modules/@adiwajshing/baileys/lib/Utils/signal.js
1129 views
"use strict";1var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {2if (k2 === undefined) k2 = k;3var desc = Object.getOwnPropertyDescriptor(m, k);4if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {5desc = { enumerable: true, get: function() { return m[k]; } };6}7Object.defineProperty(o, k2, desc);8}) : (function(o, m, k, k2) {9if (k2 === undefined) k2 = k;10o[k2] = m[k];11}));12var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {13Object.defineProperty(o, "default", { enumerable: true, value: v });14}) : function(o, v) {15o["default"] = v;16});17var __importStar = (this && this.__importStar) || function (mod) {18if (mod && mod.__esModule) return mod;19var result = {};20if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);21__setModuleDefault(result, mod);22return result;23};24Object.defineProperty(exports, "__esModule", { value: true });25exports.getNextPreKeysNode = exports.getNextPreKeys = exports.extractDeviceJids = exports.parseAndInjectE2ESessions = exports.encryptSenderKeyMsgSignalProto = exports.encryptSignalProto = exports.decryptSignalProto = exports.processSenderKeyMessage = exports.decryptGroupSignalProto = exports.signalStorage = exports.xmppPreKey = exports.xmppSignedPreKey = exports.generateOrGetPreKeys = exports.getPreKeys = exports.createSignalIdentity = exports.jidToSignalSenderKeyName = exports.jidToSignalProtocolAddress = void 0;26const libsignal = __importStar(require("libsignal"));27const WASignalGroup_1 = require("../../WASignalGroup");28const Defaults_1 = require("../Defaults");29const WABinary_1 = require("../WABinary");30const crypto_1 = require("./crypto");31const generics_1 = require("./generics");32const jidToSignalAddress = (jid) => jid.split('@')[0];33const jidToSignalProtocolAddress = (jid) => {34return new libsignal.ProtocolAddress(jidToSignalAddress(jid), 0);35};36exports.jidToSignalProtocolAddress = jidToSignalProtocolAddress;37const jidToSignalSenderKeyName = (group, user) => {38return new WASignalGroup_1.SenderKeyName(group, (0, exports.jidToSignalProtocolAddress)(user)).toString();39};40exports.jidToSignalSenderKeyName = jidToSignalSenderKeyName;41const createSignalIdentity = (wid, accountSignatureKey) => {42return {43identifier: { name: wid, deviceId: 0 },44identifierKey: (0, crypto_1.generateSignalPubKey)(accountSignatureKey)45};46};47exports.createSignalIdentity = createSignalIdentity;48const getPreKeys = async ({ get }, min, limit) => {49const idList = [];50for (let id = min; id < limit; id++) {51idList.push(id.toString());52}53return get('pre-key', idList);54};55exports.getPreKeys = getPreKeys;56const generateOrGetPreKeys = (creds, range) => {57const avaliable = creds.nextPreKeyId - creds.firstUnuploadedPreKeyId;58const remaining = range - avaliable;59const lastPreKeyId = creds.nextPreKeyId + remaining - 1;60const newPreKeys = {};61if (remaining > 0) {62for (let i = creds.nextPreKeyId; i <= lastPreKeyId; i++) {63newPreKeys[i] = crypto_1.Curve.generateKeyPair();64}65}66return {67newPreKeys,68lastPreKeyId,69preKeysRange: [creds.firstUnuploadedPreKeyId, range],70};71};72exports.generateOrGetPreKeys = generateOrGetPreKeys;73const xmppSignedPreKey = (key) => ({74tag: 'skey',75attrs: {},76content: [77{ tag: 'id', attrs: {}, content: (0, generics_1.encodeBigEndian)(key.keyId, 3) },78{ tag: 'value', attrs: {}, content: key.keyPair.public },79{ tag: 'signature', attrs: {}, content: key.signature }80]81});82exports.xmppSignedPreKey = xmppSignedPreKey;83const xmppPreKey = (pair, id) => ({84tag: 'key',85attrs: {},86content: [87{ tag: 'id', attrs: {}, content: (0, generics_1.encodeBigEndian)(id, 3) },88{ tag: 'value', attrs: {}, content: pair.public }89]90});91exports.xmppPreKey = xmppPreKey;92const signalStorage = ({ creds, keys }) => ({93loadSession: async (id) => {94const { [id]: sess } = await keys.get('session', [id]);95if (sess) {96return libsignal.SessionRecord.deserialize(sess);97}98},99storeSession: async (id, session) => {100await keys.set({ 'session': { [id]: session.serialize() } });101},102isTrustedIdentity: () => {103return true;104},105loadPreKey: async (id) => {106const keyId = id.toString();107const { [keyId]: key } = await keys.get('pre-key', [keyId]);108if (key) {109return {110privKey: Buffer.from(key.private),111pubKey: Buffer.from(key.public)112};113}114},115removePreKey: (id) => keys.set({ 'pre-key': { [id]: null } }),116loadSignedPreKey: () => {117const key = creds.signedPreKey;118return {119privKey: Buffer.from(key.keyPair.private),120pubKey: Buffer.from(key.keyPair.public)121};122},123loadSenderKey: async (keyId) => {124const { [keyId]: key } = await keys.get('sender-key', [keyId]);125if (key) {126return new WASignalGroup_1.SenderKeyRecord(key);127}128},129storeSenderKey: async (keyId, key) => {130await keys.set({ 'sender-key': { [keyId]: key.serialize() } });131},132getOurRegistrationId: () => (creds.registrationId),133getOurIdentity: () => {134const { signedIdentityKey } = creds;135return {136privKey: Buffer.from(signedIdentityKey.private),137pubKey: (0, crypto_1.generateSignalPubKey)(signedIdentityKey.public),138};139}140});141exports.signalStorage = signalStorage;142const decryptGroupSignalProto = (group, user, msg, auth) => {143const senderName = (0, exports.jidToSignalSenderKeyName)(group, user);144const cipher = new WASignalGroup_1.GroupCipher((0, exports.signalStorage)(auth), senderName);145return cipher.decrypt(Buffer.from(msg));146};147exports.decryptGroupSignalProto = decryptGroupSignalProto;148const processSenderKeyMessage = async (authorJid, item, auth) => {149const builder = new WASignalGroup_1.GroupSessionBuilder((0, exports.signalStorage)(auth));150const senderName = (0, exports.jidToSignalSenderKeyName)(item.groupId, authorJid);151const senderMsg = new WASignalGroup_1.SenderKeyDistributionMessage(null, null, null, null, item.axolotlSenderKeyDistributionMessage);152const { [senderName]: senderKey } = await auth.keys.get('sender-key', [senderName]);153if (!senderKey) {154const record = new WASignalGroup_1.SenderKeyRecord();155await auth.keys.set({ 'sender-key': { [senderName]: record } });156}157await builder.process(senderName, senderMsg);158};159exports.processSenderKeyMessage = processSenderKeyMessage;160const decryptSignalProto = async (user, type, msg, auth) => {161const addr = (0, exports.jidToSignalProtocolAddress)(user);162const session = new libsignal.SessionCipher((0, exports.signalStorage)(auth), addr);163let result;164switch (type) {165case 'pkmsg':166result = await session.decryptPreKeyWhisperMessage(msg);167break;168case 'msg':169result = await session.decryptWhisperMessage(msg);170break;171}172return result;173};174exports.decryptSignalProto = decryptSignalProto;175const encryptSignalProto = async (user, buffer, auth) => {176const addr = (0, exports.jidToSignalProtocolAddress)(user);177const cipher = new libsignal.SessionCipher((0, exports.signalStorage)(auth), addr);178const { type: sigType, body } = await cipher.encrypt(buffer);179const type = sigType === 3 ? 'pkmsg' : 'msg';180return { type, ciphertext: Buffer.from(body, 'binary') };181};182exports.encryptSignalProto = encryptSignalProto;183const encryptSenderKeyMsgSignalProto = async (group, data, meId, auth) => {184const storage = (0, exports.signalStorage)(auth);185const senderName = (0, exports.jidToSignalSenderKeyName)(group, meId);186const builder = new WASignalGroup_1.GroupSessionBuilder(storage);187const { [senderName]: senderKey } = await auth.keys.get('sender-key', [senderName]);188if (!senderKey) {189const record = new WASignalGroup_1.SenderKeyRecord();190await auth.keys.set({ 'sender-key': { [senderName]: record } });191}192const senderKeyDistributionMessage = await builder.create(senderName);193const session = new WASignalGroup_1.GroupCipher(storage, senderName);194return {195ciphertext: await session.encrypt(data),196senderKeyDistributionMessageKey: senderKeyDistributionMessage.serialize(),197};198};199exports.encryptSenderKeyMsgSignalProto = encryptSenderKeyMsgSignalProto;200const parseAndInjectE2ESessions = async (node, auth) => {201const extractKey = (key) => (key ? ({202keyId: (0, WABinary_1.getBinaryNodeChildUInt)(key, 'id', 3),203publicKey: (0, crypto_1.generateSignalPubKey)((0, WABinary_1.getBinaryNodeChildBuffer)(key, 'value')),204signature: (0, WABinary_1.getBinaryNodeChildBuffer)(key, 'signature'),205}) : undefined);206const nodes = (0, WABinary_1.getBinaryNodeChildren)((0, WABinary_1.getBinaryNodeChild)(node, 'list'), 'user');207for (const node of nodes) {208(0, WABinary_1.assertNodeErrorFree)(node);209}210await Promise.all(nodes.map(async (node) => {211const signedKey = (0, WABinary_1.getBinaryNodeChild)(node, 'skey');212const key = (0, WABinary_1.getBinaryNodeChild)(node, 'key');213const identity = (0, WABinary_1.getBinaryNodeChildBuffer)(node, 'identity');214const jid = node.attrs.jid;215const registrationId = (0, WABinary_1.getBinaryNodeChildUInt)(node, 'registration', 4);216const device = {217registrationId,218identityKey: (0, crypto_1.generateSignalPubKey)(identity),219signedPreKey: extractKey(signedKey),220preKey: extractKey(key)221};222const cipher = new libsignal.SessionBuilder((0, exports.signalStorage)(auth), (0, exports.jidToSignalProtocolAddress)(jid));223await cipher.initOutgoing(device);224}));225};226exports.parseAndInjectE2ESessions = parseAndInjectE2ESessions;227const extractDeviceJids = (result, myJid, excludeZeroDevices) => {228var _a;229const { user: myUser, device: myDevice } = (0, WABinary_1.jidDecode)(myJid);230const extracted = [];231for (const node of result.content) {232const list = (_a = (0, WABinary_1.getBinaryNodeChild)(node, 'list')) === null || _a === void 0 ? void 0 : _a.content;233if (list && Array.isArray(list)) {234for (const item of list) {235const { user } = (0, WABinary_1.jidDecode)(item.attrs.jid);236const devicesNode = (0, WABinary_1.getBinaryNodeChild)(item, 'devices');237const deviceListNode = (0, WABinary_1.getBinaryNodeChild)(devicesNode, 'device-list');238if (Array.isArray(deviceListNode === null || deviceListNode === void 0 ? void 0 : deviceListNode.content)) {239for (const { tag, attrs } of deviceListNode.content) {240const device = +attrs.id;241if (tag === 'device' && // ensure the "device" tag242(!excludeZeroDevices || device !== 0) && // if zero devices are not-excluded, or device is non zero243(myUser !== user || myDevice !== device) && // either different user or if me user, not this device244(device === 0 || !!attrs['key-index']) // ensure that "key-index" is specified for "non-zero" devices, produces a bad req otherwise245) {246extracted.push({ user, device });247}248}249}250}251}252}253return extracted;254};255exports.extractDeviceJids = extractDeviceJids;256/**257* get the next N keys for upload or processing258* @param count number of pre-keys to get or generate259*/260const getNextPreKeys = async ({ creds, keys }, count) => {261const { newPreKeys, lastPreKeyId, preKeysRange } = (0, exports.generateOrGetPreKeys)(creds, count);262const update = {263nextPreKeyId: Math.max(lastPreKeyId + 1, creds.nextPreKeyId),264firstUnuploadedPreKeyId: Math.max(creds.firstUnuploadedPreKeyId, lastPreKeyId + 1)265};266await keys.set({ 'pre-key': newPreKeys });267const preKeys = await (0, exports.getPreKeys)(keys, preKeysRange[0], preKeysRange[0] + preKeysRange[1]);268return { update, preKeys };269};270exports.getNextPreKeys = getNextPreKeys;271const getNextPreKeysNode = async (state, count) => {272const { creds } = state;273const { update, preKeys } = await (0, exports.getNextPreKeys)(state, count);274const node = {275tag: 'iq',276attrs: {277xmlns: 'encrypt',278type: 'set',279to: WABinary_1.S_WHATSAPP_NET,280},281content: [282{ tag: 'registration', attrs: {}, content: (0, generics_1.encodeBigEndian)(creds.registrationId) },283{ tag: 'type', attrs: {}, content: Defaults_1.KEY_BUNDLE_TYPE },284{ tag: 'identity', attrs: {}, content: creds.signedIdentityKey.public },285{ tag: 'list', attrs: {}, content: Object.keys(preKeys).map(k => (0, exports.xmppPreKey)(preKeys[+k], +k)) },286(0, exports.xmppSignedPreKey)(creds.signedPreKey)287]288};289return { update, node };290};291exports.getNextPreKeysNode = getNextPreKeysNode;292293294