From fa7185d51b987bd477c794c7880a41bd96573731 Mon Sep 17 00:00:00 2001 From: ropic Date: Thu, 25 Jun 2026 20:53:14 -0600 Subject: [PATCH] fix: use AppStateSyncKeyData.fromObject instead of .create for app-state keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When reading app-state-sync-key data from any auth-state provider (Prisma, Redis, files), the stored JSON is deserialized with BufferJSON.reviver which correctly restores Buffer objects. However, wrapping the result with AppStateSyncKeyData.create() does not coerce the restored Buffer fields to the Uint8Array types that the proto library expects for all downstream operations. This produces incorrect keyData in the HKDF derivation step, which in turn generates a wrong AES-256-CBC key and causes "error:1C800064:Provider routines::bad decrypt" on every attempt to decode app-state mutations (labels, archives, mutes, etc.). AppStateSyncKeyData.fromObject() performs full type conversion of all fields from a plain JS object, which is exactly what is needed after JSON deserialization with BufferJSON.reviver. The fix is extracted into a shared deserializeAppStateSyncKey helper in proto-helpers.ts to avoid duplication across the three providers. Affects all three auth-state providers: Prisma, Redis, and file-based. Tested with the Prisma provider — no app-state events fired before this fix; all events (labels.association, chats.update, etc.) fire correctly after. --- src/utils/proto-helpers.ts | 8 ++++++++ src/utils/use-multi-file-auth-state-prisma.ts | 5 ++--- src/utils/use-multi-file-auth-state-provider-files.ts | 5 ++--- src/utils/use-multi-file-auth-state-redis-db.ts | 5 ++--- 4 files changed, 14 insertions(+), 9 deletions(-) create mode 100644 src/utils/proto-helpers.ts diff --git a/src/utils/proto-helpers.ts b/src/utils/proto-helpers.ts new file mode 100644 index 0000000000..39504c9e2b --- /dev/null +++ b/src/utils/proto-helpers.ts @@ -0,0 +1,8 @@ +import { WAProto as proto } from 'baileys'; + +export function deserializeAppStateSyncKey(type: string, value: unknown): unknown { + if (type === 'app-state-sync-key' && value) { + return proto.Message.AppStateSyncKeyData.fromObject(value); + } + return value; +} diff --git a/src/utils/use-multi-file-auth-state-prisma.ts b/src/utils/use-multi-file-auth-state-prisma.ts index d090780234..3764f52ee2 100644 --- a/src/utils/use-multi-file-auth-state-prisma.ts +++ b/src/utils/use-multi-file-auth-state-prisma.ts @@ -4,6 +4,7 @@ import { CacheConf, configService } from '@config/env.config'; import { Logger } from '@config/logger.config'; import { INSTANCE_DIR } from '@config/path.config'; import { AuthenticationState, BufferJSON, initAuthCreds, WAProto as proto } from 'baileys'; +import { deserializeAppStateSyncKey } from './proto-helpers'; import fs from 'fs/promises'; import path from 'path'; @@ -181,9 +182,7 @@ export default async function useMultiFileAuthStatePrisma( await Promise.all( ids.map(async (id) => { let value = await readData(`${type}-${id}`); - if (type === 'app-state-sync-key' && value) { - value = proto.Message.AppStateSyncKeyData.create(value); - } + value = deserializeAppStateSyncKey(type, value); data[id] = value; }), diff --git a/src/utils/use-multi-file-auth-state-provider-files.ts b/src/utils/use-multi-file-auth-state-provider-files.ts index eecc3100e5..6781ed4dbe 100644 --- a/src/utils/use-multi-file-auth-state-provider-files.ts +++ b/src/utils/use-multi-file-auth-state-provider-files.ts @@ -37,6 +37,7 @@ import { ProviderFiles } from '@api/provider/sessions'; import { Logger } from '@config/logger.config'; import { AuthenticationCreds, AuthenticationState, BufferJSON, initAuthCreds, proto, SignalDataTypeMap } from 'baileys'; +import { deserializeAppStateSyncKey } from './proto-helpers'; import { isNotEmpty } from 'class-validator'; export type AuthState = { @@ -115,9 +116,7 @@ export class AuthStateProvider { await Promise.all( ids.map(async (id) => { let value = await readData(`${type}-${id}`); - if (type === 'app-state-sync-key' && value) { - value = proto.Message.AppStateSyncKeyData.create(value); - } + value = deserializeAppStateSyncKey(type, value); data[id] = value; }), diff --git a/src/utils/use-multi-file-auth-state-redis-db.ts b/src/utils/use-multi-file-auth-state-redis-db.ts index e0981c700c..4da4b5f0cd 100644 --- a/src/utils/use-multi-file-auth-state-redis-db.ts +++ b/src/utils/use-multi-file-auth-state-redis-db.ts @@ -1,6 +1,7 @@ import { CacheService } from '@api/services/cache.service'; import { Logger } from '@config/logger.config'; import { AuthenticationCreds, AuthenticationState, initAuthCreds, proto, SignalDataTypeMap } from 'baileys'; +import { deserializeAppStateSyncKey } from './proto-helpers'; export async function useMultiFileAuthStateRedisDb( instanceName: string, @@ -60,9 +61,7 @@ export async function useMultiFileAuthStateRedisDb( await Promise.all( ids.map(async (id) => { let value = await readData(`${type}-${id}`); - if (type === 'app-state-sync-key' && value) { - value = proto.Message.AppStateSyncKeyData.create(value); - } + value = deserializeAppStateSyncKey(type, value); data[id] = value; }),