diff --git a/package.json b/package.json index 10ffa7f6505..b5826926a3f 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "@cacheable/node-cache": "^1.4.0", "@hapi/boom": "^9.1.3", "async-mutex": "^0.5.0", - "libsignal": "git+https://github.com/whiskeysockets/libsignal-node", + "libsignal": "git+https://github.com/jlucaso1/libsignal-node#feat-custom-logger", "lru-cache": "^11.1.0", "music-metadata": "^11.7.0", "p-queue": "^9.0.0", diff --git a/src/Signal/libsignal.ts b/src/Signal/libsignal.ts index 2e2654dfba9..29889bbf2c8 100644 --- a/src/Signal/libsignal.ts +++ b/src/Signal/libsignal.ts @@ -1,4 +1,3 @@ -/* @ts-ignore */ import * as libsignal from 'libsignal' import { LRUCache } from 'lru-cache' import type { LIDMapping, SignalAuthState, SignalKeyStoreWithTransaction } from '../Types' @@ -26,7 +25,7 @@ export function makeLibSignalRepository( pnToLIDFunc?: (jids: string[]) => Promise ): SignalRepositoryWithLIDStore { const lidMapping = new LIDMappingStore(auth.keys as SignalKeyStoreWithTransaction, logger, pnToLIDFunc) - const storage = signalStorage(auth, lidMapping) + const storage = signalStorage(auth, lidMapping, logger) const parsedKeys = auth.keys as SignalKeyStoreWithTransaction const migratedSessionCache = new LRUCache({ @@ -77,7 +76,7 @@ export function makeLibSignalRepository( }, async decryptMessage({ jid, type, ciphertext }) { const addr = jidToSignalProtocolAddress(jid) - const session = new libsignal.SessionCipher(storage, addr) + const session = new libsignal.SessionCipher(storage, addr, logger) async function doDecrypt() { let result: Buffer @@ -102,7 +101,7 @@ export function makeLibSignalRepository( async encryptMessage({ jid, data }) { const addr = jidToSignalProtocolAddress(jid) - const cipher = new libsignal.SessionCipher(storage, addr) + const cipher = new libsignal.SessionCipher(storage, addr, logger) // Use transaction to ensure atomicity return parsedKeys.transaction(async () => { @@ -137,7 +136,7 @@ export function makeLibSignalRepository( async injectE2ESession({ jid, session }) { logger.trace({ jid }, 'injecting E2EE session') - const cipher = new libsignal.SessionBuilder(storage, jidToSignalProtocolAddress(jid)) + const cipher = new libsignal.SessionBuilder(storage, jidToSignalProtocolAddress(jid), logger) return parsedKeys.transaction(async () => { await cipher.initOutgoing(session) }, jid) @@ -296,7 +295,7 @@ export function makeLibSignalRepository( const pnSession = pnSessions[pnAddrStr] if (pnSession) { // Session exists (guaranteed from device discovery) - const fromSession = libsignal.SessionRecord.deserialize(pnSession) + const fromSession = libsignal.SessionRecord.deserialize(pnSession, logger) if (fromSession.haveOpenSession()) { // Queue for bulk update: copy to LID, delete from PN sessionUpdates[lidAddrStr] = fromSession.serialize() @@ -358,7 +357,8 @@ const jidToSignalSenderKeyName = (group: string, user: string): SenderKeyName => function signalStorage( { creds, keys }: SignalAuthState, - lidMapping: LIDMappingStore + lidMapping: LIDMappingStore, + logger?: ILogger ): SenderKeyStore & libsignal.SignalStorage { // Shared function to resolve PN signal address to LID if mapping exists const resolveLIDSignalAddress = async (id: string): Promise => { @@ -388,7 +388,7 @@ function signalStorage( const { [wireJid]: sess } = await keys.get('session', [wireJid]) if (sess) { - return libsignal.SessionRecord.deserialize(sess) + return libsignal.SessionRecord.deserialize(sess, logger) } } catch (e) { return null diff --git a/src/Socket/messages-recv.ts b/src/Socket/messages-recv.ts index 274b2732ca4..b99cdb90f4e 100644 --- a/src/Socket/messages-recv.ts +++ b/src/Socket/messages-recv.ts @@ -815,7 +815,8 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { const codePairingPublicKey = await decipherLinkPublicKey(primaryEphemeralPublicKeyWrapped) const companionSharedKey = Curve.sharedKey( authState.creds.pairingEphemeralKeyPair.private, - codePairingPublicKey + codePairingPublicKey, + logger ) const random = randomBytes(32) const linkCodeSalt = randomBytes(32) @@ -831,7 +832,11 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { const encryptIv = randomBytes(12) const encrypted = aesEncryptGCM(encryptPayload, linkCodePairingExpanded, encryptIv, Buffer.alloc(0)) const encryptedPayload = Buffer.concat([linkCodeSalt, encryptIv, encrypted]) - const identitySharedKey = Curve.sharedKey(authState.creds.signedIdentityKey.private, primaryIdentityPublicKey) + const identitySharedKey = Curve.sharedKey( + authState.creds.signedIdentityKey.private, + primaryIdentityPublicKey, + logger + ) const identityPayload = Buffer.concat([companionSharedKey, identitySharedKey, random]) authState.creds.advSecretKey = (await hkdf(identityPayload, 32, { info: 'adv_secret' })).toString('base64') await query({ diff --git a/src/Socket/socket.ts b/src/Socket/socket.ts index cb5e50701e5..c2080a03772 100644 --- a/src/Socket/socket.ts +++ b/src/Socket/socket.ts @@ -847,7 +847,7 @@ export const makeSocket = (config: SocketConfig) => { ws.on('CB:iq,,pair-success', async (stanza: BinaryNode) => { logger.debug('pair success recv') try { - const { reply, creds: updatedCreds } = configureSuccessfulPairing(stanza, creds) + const { reply, creds: updatedCreds } = configureSuccessfulPairing(stanza, creds, logger) logger.info( { me: updatedCreds.me, platform: updatedCreds.platform }, diff --git a/src/Utils/crypto.ts b/src/Utils/crypto.ts index 0e0dc2a1f45..b0f597751a2 100644 --- a/src/Utils/crypto.ts +++ b/src/Utils/crypto.ts @@ -2,6 +2,7 @@ import { createCipheriv, createDecipheriv, createHash, createHmac, randomBytes } import * as curve from 'libsignal/src/curve' import { KEY_BUNDLE_TYPE } from '../Defaults' import type { KeyPair } from '../Types' +import type { ILogger } from './logger' // insure browser & node compatibility const { subtle } = globalThis.crypto @@ -19,14 +20,14 @@ export const Curve = { public: Buffer.from(pubKey.slice(1)) } }, - sharedKey: (privateKey: Uint8Array, publicKey: Uint8Array) => { - const shared = curve.calculateAgreement(generateSignalPubKey(publicKey), privateKey) + sharedKey: (privateKey: Uint8Array, publicKey: Uint8Array, logger?: ILogger) => { + const shared = curve.calculateAgreement(generateSignalPubKey(publicKey), privateKey, logger) return Buffer.from(shared) }, sign: (privateKey: Uint8Array, buf: Uint8Array) => curve.calculateSignature(privateKey, buf), - verify: (pubKey: Uint8Array, message: Uint8Array, signature: Uint8Array) => { + verify: (pubKey: Uint8Array, message: Uint8Array, signature: Uint8Array, logger?: ILogger) => { try { - curve.verifySignature(generateSignalPubKey(pubKey), message, signature) + curve.verifySignature(generateSignalPubKey(pubKey), message, signature, logger) return true } catch (error) { return false diff --git a/src/Utils/noise-handler.ts b/src/Utils/noise-handler.ts index 3ff5f4e5c37..df97b6bd0c2 100644 --- a/src/Utils/noise-handler.ts +++ b/src/Utils/noise-handler.ts @@ -105,10 +105,10 @@ export const makeNoiseHandler = ({ finishInit, processHandshake: async ({ serverHello }: proto.HandshakeMessage, noiseKey: KeyPair) => { authenticate(serverHello!.ephemeral!) - await mixIntoKey(Curve.sharedKey(privateKey, serverHello!.ephemeral!)) + await mixIntoKey(Curve.sharedKey(privateKey, serverHello!.ephemeral!, logger)) const decStaticContent = decrypt(serverHello!.static!) - await mixIntoKey(Curve.sharedKey(privateKey, decStaticContent)) + await mixIntoKey(Curve.sharedKey(privateKey, decStaticContent, logger)) const certDecoded = decrypt(serverHello!.payload!) @@ -121,7 +121,7 @@ export const makeNoiseHandler = ({ } const keyEnc = encrypt(noiseKey.public) - await mixIntoKey(Curve.sharedKey(noiseKey.private, serverHello!.ephemeral!)) + await mixIntoKey(Curve.sharedKey(noiseKey.private, serverHello!.ephemeral!, logger)) return keyEnc }, diff --git a/src/Utils/validate-connection.ts b/src/Utils/validate-connection.ts index 1d314e61332..de2380d5754 100644 --- a/src/Utils/validate-connection.ts +++ b/src/Utils/validate-connection.ts @@ -11,6 +11,7 @@ import type { AuthenticationCreds, SignalCreds, SocketConfig } from '../Types' import { type BinaryNode, getBinaryNodeChild, jidDecode, S_WHATSAPP_NET } from '../WABinary' import { Curve, hmacSign } from './crypto' import { encodeBigEndian } from './generics' +import type { ILogger } from './logger' import { createSignalIdentity } from './signal' const getUserAgent = (config: SocketConfig): proto.ClientPayload.IUserAgent => { @@ -145,7 +146,8 @@ export const configureSuccessfulPairing = ( advSecretKey, signedIdentityKey, signalIdentities - }: Pick + }: Pick, + logger?: ILogger ) => { const msgId = stanza.attrs.id @@ -186,7 +188,7 @@ export const configureSuccessfulPairing = ( ? WA_ADV_HOSTED_ACCOUNT_SIG_PREFIX : WA_ADV_ACCOUNT_SIG_PREFIX const accountMsg = Buffer.concat([accountSignaturePrefix, deviceDetails!, signedIdentityKey.public]) - if (!Curve.verify(accountSignatureKey!, accountMsg, accountSignature!)) { + if (!Curve.verify(accountSignatureKey!, accountMsg, accountSignature!, logger)) { throw new Boom('Failed to verify account signature') } diff --git a/yarn.lock b/yarn.lock index 13b75cc13b5..6e4058ec800 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3007,7 +3007,7 @@ __metadata: jimp: "npm:^1.6.0" jiti: "npm:^2.4.2" json: "npm:^11.0.0" - libsignal: "git+https://github.com/whiskeysockets/libsignal-node" + libsignal: "git+https://github.com/jlucaso1/libsignal-node#feat-custom-logger" link-preview-js: "npm:^3.0.0" lru-cache: "npm:^11.1.0" music-metadata: "npm:^11.7.0" @@ -6976,13 +6976,13 @@ __metadata: languageName: node linkType: hard -"libsignal@git+https://github.com/whiskeysockets/libsignal-node": +"libsignal@git+https://github.com/jlucaso1/libsignal-node#feat-custom-logger": version: 2.0.1 - resolution: "libsignal@https://github.com/whiskeysockets/libsignal-node.git#commit=e81ecfc32eb74951d789ab37f7e341ab66d5fff1" + resolution: "libsignal@https://github.com/jlucaso1/libsignal-node.git#commit=98e361089320a9dbac04e5304ede77b7dfa1628a" dependencies: curve25519-js: "npm:^0.0.4" protobufjs: "npm:6.8.8" - checksum: 10c0/d1ae7d8a5fadd6bb1c486d1b2ebc388967fee57c13f52b473127c1cbd9cd647b44545ff07c2b9cc49b3dea4e25ccfcfece31c526fdbdbf065837c85d189e97a0 + checksum: 10c0/61c3589038f85ccc85fdf925bdf9a876f93642e5e591c3b6a123ba71c183bd9bb5220f229dbe5c8267cdc95ad57b6103e5a6e1b5f60593b75882be29ff838046 languageName: node linkType: hard