1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 00:03:56 +00:00

[PM-21001] Move platform code to new encrypt service interface (#14544)

* Move platform code to new encrypt service interface

* Fix tests

* Fix tests

* Fix cli build
This commit is contained in:
Bernd Schoolmann
2025-05-20 19:45:40 +02:00
committed by GitHub
parent 23506b0bc1
commit d93f547cfb
12 changed files with 47 additions and 107 deletions

View File

@@ -2,7 +2,6 @@ import { mock, MockProxy } from "jest-mock-extended";
import { makeEncString, makeSymmetricCryptoKey } from "../../../../spec";
import { EncryptService } from "../../../key-management/crypto/abstractions/encrypt.service";
import { Utils } from "../../misc/utils";
import Domain from "./domain-base";
import { EncString } from "./enc-string";
@@ -22,24 +21,13 @@ describe("DomainBase", () => {
});
function setUpCryptography() {
encryptService.encrypt.mockImplementation((value) => {
let data: string;
if (typeof value === "string") {
data = value;
} else {
data = Utils.fromBufferToUtf8(value);
}
encryptService.encryptString.mockImplementation((value) =>
Promise.resolve(makeEncString(value)),
);
return Promise.resolve(makeEncString(data));
});
encryptService.decryptToUtf8.mockImplementation((value) => {
encryptService.decryptString.mockImplementation((value) => {
return Promise.resolve(value.data);
});
encryptService.decryptToBytes.mockImplementation((value) => {
return Promise.resolve(value.dataBytes);
});
}
describe("decryptWithKey", () => {
@@ -82,7 +70,7 @@ describe("DomainBase", () => {
const domain = new TestDomain();
domain.encToString = await encryptService.encrypt("string", key);
domain.encToString = await encryptService.encryptString("string", key);
const decrypted = await domain["decryptObjWithKey"](["encToString"], key, encryptService);
@@ -96,8 +84,8 @@ describe("DomainBase", () => {
const domain = new TestDomain();
domain.encToString = await encryptService.encrypt("string", key);
domain.encString2 = await encryptService.encrypt("string2", key);
domain.encToString = await encryptService.encryptString("string", key);
domain.encString2 = await encryptService.encryptString("string2", key);
const decrypted = await domain["decryptObjWithKey"](
["encToString", "encString2"],

View File

@@ -7,7 +7,6 @@ import { EncryptService } from "../../../key-management/crypto/abstractions/encr
import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key";
import { UserKey, OrgKey } from "../../../types/key";
import { EncryptionType } from "../../enums";
import { Utils } from "../../misc/utils";
import { ContainerService } from "../../services/container.service";
import { EncString } from "./enc-string";
@@ -87,7 +86,7 @@ describe("EncString", () => {
);
const encryptService = mock<EncryptService>();
encryptService.decryptToUtf8
encryptService.decryptString
.calledWith(encString, expect.anything())
.mockResolvedValue("decrypted");
@@ -106,7 +105,7 @@ describe("EncString", () => {
it("result should be cached", async () => {
const decrypted = await encString.decrypt(null);
expect(encryptService.decryptToUtf8).toBeCalledTimes(1);
expect(encryptService.decryptString).toBeCalledTimes(1);
expect(decrypted).toBe("decrypted");
});
@@ -118,24 +117,17 @@ describe("EncString", () => {
const keyService = mock<KeyService>();
const encryptService = mock<EncryptService>();
encryptService.decryptToUtf8
encryptService.decryptString
.calledWith(encString, expect.anything())
.mockResolvedValue("decrypted");
function setupEncryption() {
encryptService.encrypt.mockImplementation(async (data, key) => {
if (typeof data === "string") {
return makeEncString(data);
} else {
return makeEncString(Utils.fromBufferToUtf8(data));
}
encryptService.encryptString.mockImplementation(async (data, key) => {
return makeEncString(data);
});
encryptService.decryptToUtf8.mockImplementation(async (encString, key) => {
encryptService.decryptString.mockImplementation(async (encString, key) => {
return encString.data;
});
encryptService.decryptToBytes.mockImplementation(async (encString, key) => {
return encString.dataBytes;
});
}
beforeEach(() => {
@@ -148,7 +140,7 @@ describe("EncString", () => {
const key = new SymmetricCryptoKey(makeStaticByteArray(32));
await encString.decryptWithKey(key, encryptService);
expect(encryptService.decryptToUtf8).toHaveBeenCalledWith(encString, key, "domain-withkey");
expect(encryptService.decryptString).toHaveBeenCalledWith(encString, key);
});
it("fails to decrypt when key is null", async () => {
@@ -169,7 +161,7 @@ describe("EncString", () => {
});
it("fails to decrypt when encryptService throws", async () => {
encryptService.decryptToUtf8.mockRejectedValue("error");
encryptService.decryptString.mockRejectedValue("error");
const decrypted = await encString.decryptWithKey(
new SymmetricCryptoKey(makeStaticByteArray(32)),
@@ -330,7 +322,7 @@ describe("EncString", () => {
});
it("handles value it can't decrypt", async () => {
encryptService.decryptToUtf8.mockRejectedValue("error");
encryptService.decryptString.mockRejectedValue("error");
(window as any).bitwardenContainerService = new ContainerService(keyService, encryptService);
@@ -350,7 +342,7 @@ describe("EncString", () => {
await encString.decrypt(null, key);
expect(keyService.getUserKeyWithLegacySupport).not.toHaveBeenCalled();
expect(encryptService.decryptToUtf8).toHaveBeenCalledWith(encString, key, "provided-key");
expect(encryptService.decryptString).toHaveBeenCalledWith(encString, key);
});
it("gets an organization key if required", async () => {
@@ -361,11 +353,7 @@ describe("EncString", () => {
await encString.decrypt("orgId", null);
expect(keyService.getOrgKey).toHaveBeenCalledWith("orgId");
expect(encryptService.decryptToUtf8).toHaveBeenCalledWith(
encString,
orgKey,
"domain-orgkey-orgId",
);
expect(encryptService.decryptString).toHaveBeenCalledWith(encString, orgKey);
});
it("gets the user's decryption key if required", async () => {
@@ -376,11 +364,7 @@ describe("EncString", () => {
await encString.decrypt(null, null);
expect(keyService.getUserKeyWithLegacySupport).toHaveBeenCalledWith();
expect(encryptService.decryptToUtf8).toHaveBeenCalledWith(
encString,
userKey,
"domain-withlegacysupport-masterkey",
);
expect(encryptService.decryptString).toHaveBeenCalledWith(encString, userKey);
});
});

View File

@@ -163,31 +163,16 @@ export class EncString implements Encrypted {
return this.decryptedValue;
}
let decryptTrace = "provided-key";
try {
if (key == null) {
key = await this.getKeyForDecryption(orgId);
decryptTrace = orgId == null ? `domain-orgkey-${orgId}` : "domain-userkey|masterkey";
if (orgId != null) {
decryptTrace = `domain-orgkey-${orgId}`;
} else {
const cryptoService = Utils.getContainerService().getKeyService();
decryptTrace =
(await cryptoService.getUserKey()) == null
? "domain-withlegacysupport-masterkey"
: "domain-withlegacysupport-userkey";
}
}
if (key == null) {
throw new Error("No key to decrypt EncString with orgId " + orgId);
}
const encryptService = Utils.getContainerService().getEncryptService();
this.decryptedValue = await encryptService.decryptToUtf8(
this,
key,
decryptTrace == null ? context : `${decryptTrace}${context || ""}`,
);
this.decryptedValue = await encryptService.decryptString(this, key);
// FIXME: Remove when updating file. Eslint update
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
@@ -206,7 +191,7 @@ export class EncString implements Encrypted {
throw new Error("No key to decrypt EncString");
}
this.decryptedValue = await encryptService.decryptToUtf8(this, key, decryptTrace);
this.decryptedValue = await encryptService.decryptString(this, key);
// FIXME: Remove when updating file. Eslint update
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {