From f28bea4ca4e7e74504104e17932c8090345f5cc2 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Wed, 4 Mar 2026 10:58:01 +0100 Subject: [PATCH] [PM-31406] Migrate duckduckgo to purpose-built dangerous-crypto-compat function (#19223) * Introduce dangerous-compat crypto implementations * Migrate duckduckgo to purpose-built dangerous-crypto-compat function * Update typescript version --- .../package-lock.json | 10 ++-- .../native-messaging-test-runner/package.json | 2 +- .../duckduckgo-message-handler.service.ts | 55 +++++-------------- 3 files changed, 18 insertions(+), 49 deletions(-) diff --git a/apps/desktop/native-messaging-test-runner/package-lock.json b/apps/desktop/native-messaging-test-runner/package-lock.json index 42257186f90..256db666b7e 100644 --- a/apps/desktop/native-messaging-test-runner/package-lock.json +++ b/apps/desktop/native-messaging-test-runner/package-lock.json @@ -20,7 +20,7 @@ }, "devDependencies": { "@types/node": "22.19.7", - "typescript": "5.4.2" + "typescript": "5.8.2" } }, "../../../libs/common": { @@ -121,7 +121,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.7.tgz", "integrity": "sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw==", "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -376,11 +375,10 @@ } }, "node_modules/typescript": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", - "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", + "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/apps/desktop/native-messaging-test-runner/package.json b/apps/desktop/native-messaging-test-runner/package.json index 93f7949bb93..44a88e0aa20 100644 --- a/apps/desktop/native-messaging-test-runner/package.json +++ b/apps/desktop/native-messaging-test-runner/package.json @@ -25,7 +25,7 @@ }, "devDependencies": { "@types/node": "22.19.7", - "typescript": "5.4.2" + "typescript": "5.8.2" }, "_moduleAliases": { "@bitwarden/common": "dist/libs/common/src", diff --git a/apps/desktop/src/services/duckduckgo-message-handler.service.ts b/apps/desktop/src/services/duckduckgo-message-handler.service.ts index fb3309c5b2a..8e444586e28 100644 --- a/apps/desktop/src/services/duckduckgo-message-handler.service.ts +++ b/apps/desktop/src/services/duckduckgo-message-handler.service.ts @@ -4,14 +4,17 @@ import { Injectable } from "@angular/core"; import { firstValueFrom } from "rxjs"; import { NativeMessagingVersion } from "@bitwarden/common/enums"; +import { DANGEROUS_aesDecryptDuckDuckGoNoPaddingAes256CbcHmac } from "@bitwarden/common/key-management/crypto"; import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service"; import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; +import { DuckDuckGoEncstring } from "@bitwarden/common/key-management/crypto/dangerous/dangerous_duckduckgo_crypto"; import { EncryptedString, EncString, } from "@bitwarden/common/key-management/crypto/models/enc-string"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; +import { EncryptionType } from "@bitwarden/common/platform/enums"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { DialogService } from "@bitwarden/components"; @@ -192,7 +195,7 @@ export class DuckDuckGoMessageHandlerService { try { const decryptedResult = await this.decryptDuckDuckGoEncString( - message.encryptedCommand as EncString, + message.encryptedCommand.encryptedString as DuckDuckGoEncstring, this.duckduckgoSharedSecret, ); return JSON.parse(decryptedResult); @@ -248,50 +251,18 @@ export class DuckDuckGoMessageHandlerService { * This function also trims null characters that are a result of the null-padding from the end of the message. */ private async decryptDuckDuckGoEncString( - encString: EncString, + encString: DuckDuckGoEncstring, 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 as null, - // so null characters need to be trimmed from the end of the message for the last - // CBC-block. - private trimNullCharsFromMessage(message: string): string { - const charNull = 0; - const charRightCurlyBrace = 125; - const charRightBracket = 93; - - for (let i = message.length - 1; i >= 0; i--) { - if (message.charCodeAt(i) === charNull) { - message = message.substring(0, message.length - 1); - } else if ( - message.charCodeAt(i) === charRightCurlyBrace || - message.charCodeAt(i) === charRightBracket - ) { - break; + const keyInner = key.inner(); + switch (keyInner.type) { + case EncryptionType.AesCbc256_HmacSha256_B64: { + const decryptedBytes = DANGEROUS_aesDecryptDuckDuckGoNoPaddingAes256CbcHmac( + encString, + keyInner, + ); + return Utils.fromArrayToUtf8(decryptedBytes); } } - return message; } }