Merge pull request #1530 from adiwajshing/invalid-qr-patch

Invalid QR Patch
This commit is contained in:
Adhiraj Singh
2022-04-24 09:56:28 +05:30
committed by GitHub
25 changed files with 914 additions and 1628 deletions

View File

@@ -108,7 +108,6 @@ export const initAuthCreds = (): AuthenticationCreds => {
nextPreKeyId: 1,
firstUnuploadedPreKeyId: 1,
serverHasPreKeys: false,
accountSettings: {
unarchiveChats: false
}

View File

@@ -583,8 +583,10 @@ export const processSyncActions = (
name: action.contactAction!.fullName
}
} else if(action?.pushNameSetting) {
map['creds.update'] = map['creds.update'] || { }
map['creds.update'].me = { ...me, name: action?.pushNameSetting?.name! }
if(me?.name !== action?.pushNameSetting) {
map['creds.update'] = map['creds.update'] || { }
map['creds.update'].me = { ...me, name: action?.pushNameSetting?.name! }
}
} else if(action?.pinAction) {
update.pin = action.pinAction?.pinned ? toNumber(action.timestamp) : undefined
} else if(action?.unarchiveChatsSetting) {

View File

@@ -1,36 +1,49 @@
import { createCipheriv, createDecipheriv, createHash, createHmac, randomBytes } from 'crypto'
import * as curveJs from 'curve25519-js'
import HKDF from 'futoin-hkdf'
import * as libsignal from 'libsignal'
import { KEY_BUNDLE_TYPE } from '../Defaults'
import { KeyPair } from '../Types'
/** prefix version byte to the pub keys, required for some curve crypto functions */
export const generateSignalPubKey = (pubKey: Uint8Array | Buffer) => (
pubKey.length === 33
? pubKey
: Buffer.concat([ KEY_BUNDLE_TYPE, pubKey ])
)
export const Curve = {
generateKeyPair: (): KeyPair => {
const { public: pubKey, private: privKey } = curveJs.generateKeyPair(randomBytes(32))
const { pubKey, privKey } = libsignal.curve.generateKeyPair()
return {
private: Buffer.from(privKey),
public: Buffer.from(pubKey)
// remove version byte
public: Buffer.from((pubKey as Uint8Array).slice(1))
}
},
sharedKey: (privateKey: Uint8Array, publicKey: Uint8Array) => {
const shared = curveJs.sharedKey(privateKey, publicKey)
const shared = libsignal.curve.calculateAgreement(generateSignalPubKey(publicKey), privateKey)
return Buffer.from(shared)
},
sign: (privateKey: Uint8Array, buf: Uint8Array) => (
Buffer.from(curveJs.sign(privateKey, buf, null))
libsignal.curve.calculateSignature(privateKey, buf)
),
verify: (pubKey: Uint8Array, message: Uint8Array, signature: Uint8Array) => {
return curveJs.verify(pubKey, message, signature)
try {
libsignal.curve.verifySignature(generateSignalPubKey(pubKey), message, signature)
return true
} catch(error) {
return false
}
}
}
export const signedKeyPair = (keyPair: KeyPair, keyId: number) => {
const signKeys = Curve.generateKeyPair()
const pubKey = new Uint8Array(33)
pubKey.set([5], 0)
pubKey.set(signKeys.public, 1)
export const signedKeyPair = (identityKeyPair: KeyPair, keyId: number) => {
const preKey = Curve.generateKeyPair()
const pubKey = generateSignalPubKey(preKey.public)
const signature = Curve.sign(keyPair.private, pubKey)
const signature = Curve.sign(identityKeyPair.private, pubKey)
return { keyPair: signKeys, signature, keyId }
return { keyPair: preKey, signature, keyId }
}
/** decrypt AES 256 CBC; where the IV is prefixed to the buffer */
@@ -67,33 +80,6 @@ export function sha256(buffer: Buffer) {
}
// HKDF key expansion
// from: https://github.com/benadida/node-hkdf
export function hkdf(buffer: Uint8Array, expandedLength: number, { info, salt }: { salt?: Buffer, info?: string }) {
const hashAlg = 'sha256'
const hashLength = 32
salt = salt || Buffer.alloc(hashLength)
// now we compute the PRK
const prk = createHmac(hashAlg, salt).update(buffer).digest()
let prev = Buffer.from([])
const buffers = []
const num_blocks = Math.ceil(expandedLength / hashLength)
const infoBuff = Buffer.from(info || [])
for(var i = 0; i < num_blocks; i++) {
const hmac = createHmac(hashAlg, prk)
// XXX is there a more optimal way to build up buffers?
const input = Buffer.concat([
prev,
infoBuff,
Buffer.from(String.fromCharCode(i + 1))
])
hmac.update(input)
prev = hmac.digest()
buffers.push(prev)
}
return Buffer.concat(buffers, expandedLength)
export function hkdf(buffer: Uint8Array | Buffer, expandedLength: number, info: { salt?: Buffer, info?: string }) {
return HKDF(!Buffer.isBuffer(buffer) ? Buffer.from(buffer) : buffer, expandedLength, info)
}

View File

@@ -6,7 +6,6 @@ import { Logger } from 'pino'
import { proto } from '../../WAProto'
import { version as baileysVersion } from '../Defaults/baileys-version.json'
import { CommonBaileysEventEmitter, ConnectionState, DisconnectReason, WAVersion } from '../Types'
import { Binary } from '../WABinary'
const PLATFORM_MAP = {
'aix': 'AIX',
@@ -41,16 +40,14 @@ export const BufferJSON = {
}
}
export const writeRandomPadMax16 = (e: Binary) => {
function r(e: Binary, t: number) {
for(var r = 0; r < t; r++) {
e.writeUint8(t)
}
export const writeRandomPadMax16 = (msg: Uint8Array) => {
const pad = randomBytes(1)
pad[0] &= 0xf
if(!pad[0]) {
pad[0] = 0xf
}
var t = randomBytes(1)
r(e, 1 + (15 & t[0]))
return e
return Buffer.concat([msg, Buffer.alloc(pad[0], pad[0])])
}
export const unpadRandomMax16 = (e: Uint8Array | Buffer) => {
@@ -68,24 +65,13 @@ export const unpadRandomMax16 = (e: Uint8Array | Buffer) => {
}
export const encodeWAMessage = (message: proto.IMessage) => (
Buffer.from(
writeRandomPadMax16(
new Binary(proto.Message.encode(message).finish())
).readByteArray()
writeRandomPadMax16(
proto.Message.encode(message).finish()
)
)
export const generateRegistrationId = () => (
Uint16Array.from(randomBytes(2))[0] & 0x3fff
)
export const encodeInt = (e: number, t: number) => {
for(var r = t, a = new Uint8Array(e), i = e - 1; i >= 0; i--) {
a[i] = 255 & r
r >>>= 8
}
return a
export const generateRegistrationId = (): number => {
return Uint16Array.from(randomBytes(2))[0] & 16383
}
export const encodeBigEndian = (e: number, t = 4) => {
@@ -255,6 +241,12 @@ export const fetchLatestBaileysVersion = async() => {
}
}
/** unique message tag prefix for MD clients */
export const generateMdTagPrefix = () => {
const bytes = randomBytes(4)
return `${bytes.readUInt16BE()}.${bytes.readUInt16BE(2)}-`
}
const STATUS_MAP: { [_: string]: proto.WebMessageInfo.WebMessageInfoStatus } = {
'played': proto.WebMessageInfo.WebMessageInfoStatus.PLAYED,
'read': proto.WebMessageInfo.WebMessageInfoStatus.READ,

View File

@@ -327,28 +327,30 @@ export const generateWAMessageContent = async(
m = { buttonsMessage }
} else if('templateButtons' in message && !!message.templateButtons) {
const templateMessage: proto.ITemplateMessage = {
hydratedTemplate: {
hydratedButtons: message.templateButtons
}
const msg: proto.IHydratedFourRowTemplate = {
hydratedButtons: message.templateButtons
}
if('text' in message) {
templateMessage.hydratedTemplate.hydratedContentText = message.text
msg.hydratedContentText = message.text
} else {
if('caption' in message) {
templateMessage.hydratedTemplate.hydratedContentText = message.caption
msg.hydratedContentText = message.caption
}
Object.assign(templateMessage.hydratedTemplate, m)
Object.assign(msg, m)
}
if('footer' in message && !!message.footer) {
templateMessage.hydratedTemplate.hydratedFooterText = message.footer
msg.hydratedFooterText = message.footer
}
m = { templateMessage }
m = {
templateMessage: {
hydratedTemplate: msg
}
}
}
if('sections' in message && !!message.sections) {

View File

@@ -1,12 +1,14 @@
import { Boom } from '@hapi/boom'
import { createCipheriv, createDecipheriv } from 'crypto'
import { Logger } from 'pino'
import { proto } from '../../WAProto'
import { NOISE_MODE, NOISE_WA_HEADER } from '../Defaults'
import { KeyPair } from '../Types'
import { Binary } from '../WABinary'
import { BinaryNode, decodeBinaryNode } from '../WABinary'
import { Curve, hkdf, sha256 } from './crypto'
const TAG_LENGTH = 128 >> 3
const generateIV = (counter: number) => {
const iv = new ArrayBuffer(12)
new DataView(iv).setUint32(8, counter)
@@ -14,7 +16,11 @@ const generateIV = (counter: number) => {
return new Uint8Array(iv)
}
export const makeNoiseHandler = ({ public: publicKey, private: privateKey }: KeyPair) => {
export const makeNoiseHandler = (
{ public: publicKey, private: privateKey }: KeyPair,
logger: Logger
) => {
logger = logger.child({ class: 'ns' })
const authenticate = (data: Uint8Array) => {
if(!isFinished) {
@@ -23,8 +29,7 @@ export const makeNoiseHandler = ({ public: publicKey, private: privateKey }: Key
}
const encrypt = (plaintext: Uint8Array) => {
const authTagLength = 128 >> 3
const cipher = createCipheriv('aes-256-gcm', encKey, generateIV(writeCounter), { authTagLength })
const cipher = createCipheriv('aes-256-gcm', encKey, generateIV(writeCounter), { authTagLength: TAG_LENGTH })
cipher.setAAD(hash)
const result = Buffer.concat([cipher.update(plaintext), cipher.final(), cipher.getAuthTag()])
@@ -41,9 +46,8 @@ export const makeNoiseHandler = ({ public: publicKey, private: privateKey }: Key
const iv = generateIV(isFinished ? readCounter : writeCounter)
const cipher = createDecipheriv('aes-256-gcm', decKey, iv)
// decrypt additional adata
const tagLength = 128 >> 3
const enc = ciphertext.slice(0, ciphertext.length - tagLength)
const tag = ciphertext.slice(ciphertext.length - tagLength)
const enc = ciphertext.slice(0, ciphertext.length - TAG_LENGTH)
const tag = ciphertext.slice(ciphertext.length - TAG_LENGTH)
// set additional data
cipher.setAAD(hash)
cipher.setAuthTag(tag)
@@ -94,8 +98,7 @@ export const makeNoiseHandler = ({ public: publicKey, private: privateKey }: Key
let isFinished = false
let sentIntro = false
const outBinary = new Binary()
const inBinary = new Binary()
let inBytes = Buffer.alloc(0)
authenticate(NOISE_WA_HEADER)
authenticate(publicKey)
@@ -114,7 +117,7 @@ export const makeNoiseHandler = ({ public: publicKey, private: privateKey }: Key
mixIntoKey(Curve.sharedKey(privateKey, decStaticContent))
const certDecoded = decrypt(serverHello!.payload!)
const { details: certDetails, signature: certSignature } = proto.NoiseCertificate.decode(certDecoded)
const { details: certDetails } = proto.NoiseCertificate.decode(certDecoded)
const { key: certKey } = proto.NoiseCertificateDetails.decode(certDetails)
@@ -133,47 +136,48 @@ export const makeNoiseHandler = ({ public: publicKey, private: privateKey }: Key
}
const introSize = sentIntro ? 0 : NOISE_WA_HEADER.length
outBinary.ensureAdditionalCapacity(introSize + 3 + data.byteLength)
const frame = Buffer.alloc(introSize + 3 + data.byteLength)
if(!sentIntro) {
outBinary.writeByteArray(NOISE_WA_HEADER)
frame.set(NOISE_WA_HEADER)
sentIntro = true
}
outBinary.writeUint8(data.byteLength >> 16)
outBinary.writeUint16(65535 & data.byteLength)
outBinary.write(data)
frame.writeUInt8(data.byteLength >> 16, introSize)
frame.writeUInt16BE(65535 & data.byteLength, introSize + 1)
frame.set(data, introSize + 3)
const bytes = outBinary.readByteArray()
return bytes as Uint8Array
return frame
},
decodeFrame: (newData: Buffer | Uint8Array, onFrame: (buff: Uint8Array | BinaryNode) => void) => {
// the binary protocol uses its own framing mechanism
// on top of the WS frames
// so we get this data and separate out the frames
const getBytesSize = () => {
return (inBinary.readUint8() << 16) | inBinary.readUint16()
if(inBytes.length >= 3) {
return (inBytes.readUInt8() << 16) | inBytes.readUInt16BE(1)
}
}
const peekSize = () => {
return !(inBinary.size() < 3) && getBytesSize() <= inBinary.size()
}
inBytes = Buffer.concat([ inBytes, newData ])
logger.trace(`recv ${newData.length} bytes, total recv ${inBytes.length} bytes`)
let size = getBytesSize()
while(size && inBytes.length >= size + 3) {
let frame: Uint8Array | BinaryNode = inBytes.slice(3, size + 3)
inBytes = inBytes.slice(size + 3)
inBinary.writeByteArray(newData)
while(inBinary.peek(peekSize)) {
const bytes = getBytesSize()
let frame: Uint8Array | BinaryNode = inBinary.readByteArray(bytes)
if(isFinished) {
const result = decrypt(frame as Uint8Array)
const unpacked = new Binary(result).decompressed()
frame = decodeBinaryNode(unpacked)
frame = decodeBinaryNode(result)
}
onFrame(frame)
}
logger.trace({ msg: (frame as any)?.attrs?.id }, 'recv frame')
inBinary.peek(peekSize)
onFrame(frame)
size = getBytesSize()
}
}
}
}

View File

@@ -1,18 +1,12 @@
import * as libsignal from 'libsignal'
import { proto } from '../../WAProto'
import { GroupCipher, GroupSessionBuilder, SenderKeyDistributionMessage, SenderKeyName, SenderKeyRecord } from '../../WASignalGroup'
import { AuthenticationCreds, KeyPair, SignalAuthState, SignalIdentity, SignalKeyStore, SignedKeyPair } from '../Types/Auth'
import { assertNodeErrorFree, BinaryNode, getBinaryNodeChild, getBinaryNodeChildBuffer, getBinaryNodeChildren, getBinaryNodeChildUInt, jidDecode, JidWithDevice } from '../WABinary'
import { Curve } from './crypto'
import { KEY_BUNDLE_TYPE } from '../Defaults'
import { AuthenticationCreds, AuthenticationState, KeyPair, SignalAuthState, SignalIdentity, SignalKeyStore, SignedKeyPair } from '../Types/Auth'
import { assertNodeErrorFree, BinaryNode, getBinaryNodeChild, getBinaryNodeChildBuffer, getBinaryNodeChildren, getBinaryNodeChildUInt, jidDecode, JidWithDevice, S_WHATSAPP_NET } from '../WABinary'
import { Curve, generateSignalPubKey } from './crypto'
import { encodeBigEndian } from './generics'
export const generateSignalPubKey = (pubKey: Uint8Array | Buffer) => {
const newPub = Buffer.alloc(33)
newPub.set([5], 0)
newPub.set(pubKey, 1)
return newPub
}
const jidToSignalAddress = (jid: string) => jid.split('@')[0]
export const jidToSignalProtocolAddress = (jid: string) => {
@@ -60,7 +54,6 @@ export const generateOrGetPreKeys = (creds: AuthenticationCreds, range: number)
}
}
export const xmppSignedPreKey = (key: SignedKeyPair): BinaryNode => (
{
tag: 'skey',
@@ -273,4 +266,46 @@ export const extractDeviceJids = (result: BinaryNode, myJid: string, excludeZero
}
return extracted
}
/**
* get the next N keys for upload or processing
* @param count number of pre-keys to get or generate
*/
export const getNextPreKeys = async({ creds, keys }: AuthenticationState, count: number) => {
const { newPreKeys, lastPreKeyId, preKeysRange } = generateOrGetPreKeys(creds, count)
const update: Partial<AuthenticationCreds> = {
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 }
}
export const getNextPreKeysNode = async(state: AuthenticationState, count: number) => {
const { creds } = state
const { update, preKeys } = await getNextPreKeys(state, count)
const node: BinaryNode = {
tag: 'iq',
attrs: {
xmlns: 'encrypt',
type: 'set',
to: S_WHATSAPP_NET,
},
content: [
{ tag: 'registration', attrs: { }, content: encodeBigEndian(creds.registrationId) },
{ tag: 'type', attrs: { }, content: 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 }
}

View File

@@ -1,15 +1,16 @@
import { Boom } from '@hapi/boom'
import { createHash } from 'crypto'
import { proto } from '../../WAProto'
import { KEY_BUNDLE_TYPE } from '../Defaults'
import type { AuthenticationCreds, SignalCreds, SocketConfig } from '../Types'
import { BinaryNode, getAllBinaryNodeChildren, jidDecode, S_WHATSAPP_NET } from '../WABinary'
import { BinaryNode, getBinaryNodeChild, jidDecode, S_WHATSAPP_NET } from '../WABinary'
import { Curve, hmacSign } from './crypto'
import { encodeInt } from './generics'
import { encodeBigEndian } from './generics'
import { createSignalIdentity } from './signal'
type ClientPayloadConfig = Pick<SocketConfig, 'version' | 'browser'>
const getUserAgent = ({ version }: Pick<SocketConfig, 'version'>): proto.IUserAgent => ({
const getUserAgent = ({ version, browser }: ClientPayloadConfig): proto.IUserAgent => ({
appVersion: {
primary: version[0],
secondary: version[1],
@@ -19,12 +20,12 @@ const getUserAgent = ({ version }: Pick<SocketConfig, 'version'>): proto.IUserAg
releaseChannel: proto.UserAgent.UserAgentReleaseChannel.RELEASE,
mcc: '000',
mnc: '000',
osVersion: '0.1',
osVersion: browser[2],
manufacturer: '',
device: 'Desktop',
osBuildNumber: '0.1',
osBuildNumber: browser[2],
localeLanguageIso6391: 'en',
localeCountryIso31661Alpha2: 'US',
localeCountryIso31661Alpha2: 'en',
})
const getWebInfo = (): proto.IWebInfo => ({
@@ -33,7 +34,6 @@ const getWebInfo = (): proto.IWebInfo => ({
const getClientPayload = (config: ClientPayloadConfig): proto.IClientPayload => {
return {
passive: true,
connectType: proto.ClientPayload.ClientPayloadConnectType.WIFI_UNKNOWN,
connectReason: proto.ClientPayload.ClientPayloadConnectReason.USER_ACTIVATED,
userAgent: getUserAgent(config),
@@ -45,6 +45,7 @@ export const generateLoginNode = (userJid: string, config: ClientPayloadConfig):
const { user, device } = jidDecode(userJid)
const payload: proto.IClientPayload = {
...getClientPayload(config),
passive: true,
username: +user,
device: device,
}
@@ -65,11 +66,11 @@ export const generateRegistrationNode = (
const companion: proto.ICompanionProps = {
os: config.browser[0],
version: {
primary: +(browserVersion[0] || 10),
secondary: +(browserVersion[1] || 0),
primary: +(browserVersion[0] || 0),
secondary: +(browserVersion[1] || 1),
tertiary: +(browserVersion[2] || 0),
},
platformType: proto.CompanionProps.CompanionPropsPlatformType[config.browser[1].toUpperCase()] || proto.CompanionProps.CompanionPropsPlatformType.CHROME,
platformType: proto.CompanionProps.CompanionPropsPlatformType[config.browser[1].toUpperCase()] || proto.CompanionProps.CompanionPropsPlatformType.UNKNOWN,
requireFullSync: false,
}
@@ -77,13 +78,14 @@ export const generateRegistrationNode = (
const registerPayload: proto.IClientPayload = {
...getClientPayload(config),
passive: false,
regData: {
buildHash: appVersionBuf,
companionProps: companionProto,
eRegid: encodeInt(4, registrationId),
eKeytype: encodeInt(1, 5),
eRegid: encodeBigEndian(registrationId),
eKeytype: KEY_BUNDLE_TYPE,
eIdent: signedIdentityKey.public,
eSkeyId: encodeInt(3, signedPreKey.keyId),
eSkeyId: encodeBigEndian(signedPreKey.keyId, 3),
eSkeyVal: signedPreKey.keyPair.public,
eSkeySig: signedPreKey.signature,
},
@@ -96,51 +98,47 @@ export const configureSuccessfulPairing = (
stanza: BinaryNode,
{ advSecretKey, signedIdentityKey, signalIdentities }: Pick<AuthenticationCreds, 'advSecretKey' | 'signedIdentityKey' | 'signalIdentities'>
) => {
const [pair] = getAllBinaryNodeChildren(stanza)
const pairContent = Array.isArray(pair.content) ? pair.content : []
const msgId = stanza.attrs.id
const deviceIdentity = pairContent.find(m => m.tag === 'device-identity')?.content
const businessName = pairContent.find(m => m.tag === 'biz')?.attrs?.name
const verifiedName = businessName || ''
const jid = pairContent.find(m => m.tag === 'device')?.attrs?.jid
const { details, hmac } = proto.ADVSignedDeviceIdentityHMAC.decode(deviceIdentity as Buffer)
const pairSuccessNode = getBinaryNodeChild(stanza, 'pair-success')
const deviceIdentityNode = getBinaryNodeChild(pairSuccessNode, 'device-identity')
const platformNode = getBinaryNodeChild(pairSuccessNode, 'platform')
const deviceNode = getBinaryNodeChild(pairSuccessNode, 'device')
const businessNode = getBinaryNodeChild(pairSuccessNode, 'biz')
if(!deviceIdentityNode || !deviceNode) {
throw new Boom('Missing device-identity or device in pair success node', { data: stanza })
}
const bizName = businessNode?.attrs.name
const jid = deviceNode.attrs.jid
const { details, hmac } = proto.ADVSignedDeviceIdentityHMAC.decode(deviceIdentityNode.content as Buffer)
// check HMAC matches
const advSign = hmacSign(details, Buffer.from(advSecretKey, 'base64'))
if(Buffer.compare(hmac, advSign) !== 0) {
throw new Boom('Invalid pairing')
throw new Boom('Invalid account signature')
}
const account = proto.ADVSignedDeviceIdentity.decode(details)
const { accountSignatureKey, accountSignature } = account
const accountMsg = Buffer.concat([
Buffer.from([6, 0]),
account.details,
signedIdentityKey.public
])
const { accountSignatureKey, accountSignature, details: deviceDetails } = account
// verify the device signature matches
const accountMsg = Buffer.concat([ Buffer.from([6, 0]), deviceDetails, signedIdentityKey.public ])
if(!Curve.verify(accountSignatureKey, accountMsg, accountSignature)) {
throw new Boom('Failed to verify account signature')
}
const deviceMsg = Buffer.concat([
new Uint8Array([6, 1]),
account.details,
signedIdentityKey.public,
account.accountSignatureKey
])
// sign the details with our identity key
const deviceMsg = Buffer.concat([ Buffer.from([6, 1]), deviceDetails, signedIdentityKey.public, accountSignatureKey ])
account.deviceSignature = Curve.sign(signedIdentityKey.private, deviceMsg)
// do not provide the "accountSignatureKey" back
account.accountSignatureKey = null
const identity = createSignalIdentity(jid, accountSignatureKey)
const accountEnc = proto.ADVSignedDeviceIdentity.encode(account).finish()
const keyIndex = proto.ADVDeviceIdentity.decode(account.details).keyIndex
const accountEnc = proto.ADVSignedDeviceIdentity.encode({
...account.toJSON(),
accountSignatureKey: undefined
}).finish()
const deviceIdentity = proto.ADVDeviceIdentity.decode(account.details)
const reply: BinaryNode = {
tag: 'iq',
@@ -156,7 +154,7 @@ export const configureSuccessfulPairing = (
content: [
{
tag: 'device-identity',
attrs: { 'key-index': `${keyIndex}` },
attrs: { 'key-index': deviceIdentity.keyIndex.toString() },
content: accountEnc
}
]
@@ -166,9 +164,14 @@ export const configureSuccessfulPairing = (
const authUpdate: Partial<AuthenticationCreds> = {
account,
me: { id: jid, verifiedName },
signalIdentities: [...(signalIdentities || []), identity]
me: { id: jid, name: bizName },
signalIdentities: [
...(signalIdentities || []),
identity
],
platform: platformNode?.attrs.name
}
return {
creds: authUpdate,
reply