[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
This commit is contained in:
Bernd Schoolmann 2026-03-04 10:58:01 +01:00 committed by GitHub
parent 71fa320557
commit f28bea4ca4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 18 additions and 49 deletions

View File

@ -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"

View File

@ -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",

View File

@ -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<string> {
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;
}
}