From 7124f8c4bc0c6eff4e45084ca308748c1308084c Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Thu, 22 May 2025 19:28:30 +0200 Subject: [PATCH] Fix ddg integration when sdk is enabled for decryption --- .../duckduckgo-message-handler.service.ts | 45 ++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/apps/desktop/src/services/duckduckgo-message-handler.service.ts b/apps/desktop/src/services/duckduckgo-message-handler.service.ts index 6fb91231be1..60d69e402c4 100644 --- a/apps/desktop/src/services/duckduckgo-message-handler.service.ts +++ b/apps/desktop/src/services/duckduckgo-message-handler.service.ts @@ -188,13 +188,10 @@ export class DuckDuckGoMessageHandlerService { } try { - let decryptedResult = await this.encryptService.decryptString( + const decryptedResult = await this.decryptDuckDuckGoEncString( message.encryptedCommand as EncString, this.duckduckgoSharedSecret, ); - - decryptedResult = this.trimNullCharsFromMessage(decryptedResult); - return JSON.parse(decryptedResult); } catch { this.sendResponse({ @@ -237,7 +234,45 @@ export class DuckDuckGoMessageHandlerService { ipc.platform.nativeMessaging.sendReply(response); } - // Trim all null bytes padded at the end of messages. This happens with C encryption libraries. + /* + * Bitwarden type 2 (AES256-CBC-HMAC256) use PKCS7 padding. + * DuckDuckGo does not use PKCS7 padding; and instead fills the last CBC block with null bytes. + * ref: https://github.com/duckduckgo/apple-browsers/blob/04d678b447869c3a640714718a466b36407db8b6/macOS/DuckDuckGo/PasswordManager/Bitwarden/Services/BWEncryption.m#L141 + * + * This is incompatible which means the default encryptService cannot be used to decrypt the message, + * A custom EncString decrypt operation is needed, and encryptService cannot be used. + * + * This function also trims null characters that are a result of the lack of padding from the end of the message. + */ + private async decryptDuckDuckGoEncString( + encString: EncString, + key: SymmetricCryptoKey, + ): Promise { + const fastParams = this.cryptoFunctionService.aesDecryptFastParameters( + encString.data, + encString.iv, + encString.mac, + key, + ); + + const computedMac = await this.cryptoFunctionService.hmacFast( + fastParams.macData, + fastParams.macKey, + "sha256", + ); + const macsEqual = await this.cryptoFunctionService.compareFast(fastParams.mac, computedMac); + if (!macsEqual) { + return null; + } + const decryptedPaddedString = await this.cryptoFunctionService.aesDecryptFast({ + mode: "cbc", + parameters: fastParams, + }); + return this.trimNullCharsFromMessage(decryptedPaddedString); + } + + // DuckDuckGo does not use PKCS7 padding, but instead leaves the values to null + // so null characters need to be trimmed from the end of the message. This means that private trimNullCharsFromMessage(message: string): string { const charNull = 0; const charRightCurlyBrace = 125;