1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-25 00:53:22 +00:00

Merge branch 'km/encstring-remove-decrypt-vault' into km/decrypt-obj

This commit is contained in:
Bernd Schoolmann
2025-10-29 16:20:04 +01:00
8 changed files with 43 additions and 40 deletions

View File

@@ -186,15 +186,15 @@ export class EditCommand {
return Response.notFound();
}
let folderView = await folder.decrypt();
const userKey = await firstValueFrom(this.keyService.userKey$(activeUserId));
let folderView = await folder.decrypt(userKey);
folderView = FolderExport.toView(req, folderView);
const userKey = await this.keyService.getUserKey(activeUserId);
const encFolder = await this.folderService.encrypt(folderView, userKey);
try {
const folder = await this.folderApiService.save(encFolder, activeUserId);
const updatedFolder = new Folder(folder);
const decFolder = await updatedFolder.decrypt();
const decFolder = await updatedFolder.decrypt(userKey);
const res = new FolderResponse(decFolder);
return Response.success(res);
} catch (e) {

View File

@@ -417,10 +417,11 @@ export class GetCommand extends DownloadCommand {
private async getFolder(id: string) {
let decFolder: FolderView = null;
const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
const userKey = await firstValueFrom(this.keyService.userKey$(activeUserId));
if (Utils.isGuid(id)) {
const folder = await this.folderService.getFromState(id, activeUserId);
if (folder != null) {
decFolder = await folder.decrypt();
decFolder = await folder.decrypt(userKey);
}
} else if (id.trim() !== "") {
let folders = await this.folderService.getAllDecryptedFromState(activeUserId);

View File

@@ -181,12 +181,12 @@ export class CreateCommand {
private async createFolder(req: FolderExport) {
const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
const userKey = await this.keyService.getUserKey(activeUserId);
const userKey = await firstValueFrom(this.keyService.userKey$(activeUserId));
const folder = await this.folderService.encrypt(FolderExport.toView(req), userKey);
try {
const folderData = await this.folderApiService.save(folder, activeUserId);
const newFolder = new Folder(folderData);
const decFolder = await newFolder.decrypt();
const decFolder = await newFolder.decrypt(userKey);
const res = new FolderResponse(decFolder);
return Response.success(res);
} catch (e) {

View File

@@ -39,6 +39,8 @@ import { IdentityView } from "../../models/view/identity.view";
import { LoginView } from "../../models/view/login.view";
import { CipherPermissionsApi } from "../api/cipher-permissions.api";
const mockSymmetricKey = new SymmetricCryptoKey(makeStaticByteArray(64));
describe("Cipher DTO", () => {
it("Convert from empty CipherData", () => {
const data = new CipherData();
@@ -100,6 +102,9 @@ describe("Cipher DTO", () => {
const cipherService = mock<CipherService>();
encryptService.unwrapSymmetricKey.mockRejectedValue(new Error("Failed to unwrap key"));
cipherService.getKeyForCipherKeyDecryption.mockResolvedValue(
new SymmetricCryptoKey(makeStaticByteArray(64)),
);
(window as any).bitwardenContainerService = new ContainerService(keyService, encryptService);
@@ -319,7 +324,6 @@ describe("Cipher DTO", () => {
const keyService = mock<KeyService>();
const encryptService = mock<EncryptService>();
const cipherService = mock<CipherService>();
encryptService.unwrapSymmetricKey.mockResolvedValue(
new SymmetricCryptoKey(makeStaticByteArray(64)),
@@ -327,9 +331,7 @@ describe("Cipher DTO", () => {
(window as any).bitwardenContainerService = new ContainerService(keyService, encryptService);
const cipherView = await cipher.decrypt(
await cipherService.getKeyForCipherKeyDecryption(cipher, mockUserId),
);
const cipherView = await cipher.decrypt(mockSymmetricKey);
expect(cipherView).toMatchObject({
id: "id",
@@ -447,7 +449,6 @@ describe("Cipher DTO", () => {
const keyService = mock<KeyService>();
const encryptService = mock<EncryptService>();
const cipherService = mock<CipherService>();
encryptService.unwrapSymmetricKey.mockResolvedValue(
new SymmetricCryptoKey(makeStaticByteArray(64)),
@@ -455,9 +456,7 @@ describe("Cipher DTO", () => {
(window as any).bitwardenContainerService = new ContainerService(keyService, encryptService);
const cipherView = await cipher.decrypt(
await cipherService.getKeyForCipherKeyDecryption(cipher, mockUserId),
);
const cipherView = await cipher.decrypt(mockSymmetricKey);
expect(cipherView).toMatchObject({
id: "id",
@@ -593,7 +592,6 @@ describe("Cipher DTO", () => {
const keyService = mock<KeyService>();
const encryptService = mock<EncryptService>();
const cipherService = mock<CipherService>();
encryptService.unwrapSymmetricKey.mockResolvedValue(
new SymmetricCryptoKey(makeStaticByteArray(64)),
@@ -601,9 +599,7 @@ describe("Cipher DTO", () => {
(window as any).bitwardenContainerService = new ContainerService(keyService, encryptService);
const cipherView = await cipher.decrypt(
await cipherService.getKeyForCipherKeyDecryption(cipher, mockUserId),
);
const cipherView = await cipher.decrypt(mockSymmetricKey);
expect(cipherView).toMatchObject({
id: "id",
@@ -763,7 +759,6 @@ describe("Cipher DTO", () => {
const keyService = mock<KeyService>();
const encryptService = mock<EncryptService>();
const cipherService = mock<CipherService>();
encryptService.unwrapSymmetricKey.mockResolvedValue(
new SymmetricCryptoKey(makeStaticByteArray(64)),
@@ -771,9 +766,7 @@ describe("Cipher DTO", () => {
(window as any).bitwardenContainerService = new ContainerService(keyService, encryptService);
const cipherView = await cipher.decrypt(
await cipherService.getKeyForCipherKeyDecryption(cipher, mockUserId),
);
const cipherView = await cipher.decrypt(mockSymmetricKey);
expect(cipherView).toMatchObject({
id: "id",

View File

@@ -33,7 +33,7 @@ describe("Folder", () => {
folder.name = mockEnc("encName");
folder.revisionDate = new Date("2022-01-31T12:00:00.000Z");
const view = await folder.decrypt();
const view = await folder.decrypt(null);
expect(view).toEqual({
id: "id",

View File

@@ -39,8 +39,8 @@ export class Folder extends Domain {
this.revisionDate = obj.revisionDate != null ? new Date(obj.revisionDate) : null;
}
decrypt(): Promise<FolderView> {
return this.decryptObj<Folder, FolderView>(this, new FolderView(this), ["name"], null);
decrypt(key: SymmetricCryptoKey): Promise<FolderView> {
return this.decryptObj<Folder, FolderView>(this, new FolderView(this), ["name"], null, key);
}
async decryptWithKey(

View File

@@ -1533,10 +1533,15 @@ export class CipherService implements CipherServiceAbstraction {
}
async getKeyForCipherKeyDecryption(cipher: Cipher, userId: UserId): Promise<UserKey | OrgKey> {
return (
(await this.keyService.getOrgKey(cipher.organizationId)) ||
((await this.keyService.getUserKey(userId)) as UserKey)
);
if (cipher.organizationId == null) {
return await firstValueFrom(this.keyService.userKey$(userId));
} else {
return await firstValueFrom(
this.keyService
.orgKeys$(userId)
.pipe(map((orgKeys) => orgKeys[cipher.organizationId as OrganizationId] as OrgKey)),
);
}
}
async setAddEditCipherInfo(value: AddEditCipherInfo, userId: UserId) {

View File

@@ -15,7 +15,7 @@ import {
} from "@bitwarden/common/models/export";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { OrganizationId } from "@bitwarden/common/types/guid";
import { OrganizationId, UserId } from "@bitwarden/common/types/guid";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
import { KeyService } from "@bitwarden/key-management";
@@ -45,6 +45,7 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer {
}
async parse(data: string): Promise<ImportResult> {
const account = await firstValueFrom(this.accountService.activeAccount$);
this.result = new ImportResult();
const results: BitwardenJsonExport = JSON.parse(data);
if (results == null || results.items == null) {
@@ -53,9 +54,9 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer {
}
if (results.encrypted) {
await this.parseEncrypted(results as any);
await this.parseEncrypted(results as any, account.id);
} else {
await this.parseDecrypted(results as any);
await this.parseDecrypted(results as any, account.id);
}
return this.result;
@@ -63,14 +64,13 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer {
private async parseEncrypted(
results: BitwardenEncryptedIndividualJsonExport | BitwardenEncryptedOrgJsonExport,
userId: UserId,
) {
const account = await firstValueFrom(this.accountService.activeAccount$);
if (results.encKeyValidation_DO_NOT_EDIT != null) {
const orgKeys = await firstValueFrom(this.keyService.orgKeys$(account.id));
const orgKeys = await firstValueFrom(this.keyService.orgKeys$(userId));
let keyForDecryption: SymmetricCryptoKey = orgKeys?.[this.organizationId];
if (keyForDecryption == null) {
keyForDecryption = await firstValueFrom(this.keyService.userKey$(account.id));
keyForDecryption = await firstValueFrom(this.keyService.userKey$(userId));
}
const encKeyValidation = new EncString(results.encKeyValidation_DO_NOT_EDIT);
try {
@@ -84,7 +84,7 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer {
const groupingsMap = this.organization
? await this.parseCollections(results as BitwardenEncryptedOrgJsonExport)
: await this.parseFolders(results as BitwardenEncryptedIndividualJsonExport);
: await this.parseFolders(results as BitwardenEncryptedIndividualJsonExport, userId);
for (const c of results.items) {
const cipher = CipherWithIdExport.toDomain(c);
@@ -114,7 +114,7 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer {
});
}
const view = await this.cipherService.decrypt(cipher, account.id);
const view = await this.cipherService.decrypt(cipher, userId);
this.cleanupCipher(view);
this.result.ciphers.push(view);
}
@@ -124,10 +124,11 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer {
private async parseDecrypted(
results: BitwardenUnEncryptedIndividualJsonExport | BitwardenUnEncryptedOrgJsonExport,
userId: UserId,
) {
const groupingsMap = this.organization
? await this.parseCollections(results as BitwardenUnEncryptedOrgJsonExport)
: await this.parseFolders(results as BitwardenUnEncryptedIndividualJsonExport);
: await this.parseFolders(results as BitwardenUnEncryptedIndividualJsonExport, userId);
results.items.forEach((c) => {
const cipher = CipherWithIdExport.toView(c);
@@ -166,11 +167,14 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer {
private async parseFolders(
data: BitwardenUnEncryptedIndividualJsonExport | BitwardenEncryptedIndividualJsonExport,
userId: UserId,
): Promise<Map<string, number>> | null {
if (data.folders == null) {
return null;
}
const userKey = await firstValueFrom(this.keyService.userKey$(userId));
const groupingsMap = new Map<string, number>();
for (const f of data.folders) {
@@ -178,7 +182,7 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer {
if (data.encrypted) {
const folder = FolderWithIdExport.toDomain(f);
if (folder != null) {
folderView = await folder.decrypt();
folderView = await folder.decrypt(userKey);
}
} else {
folderView = FolderWithIdExport.toView(f);