mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-25 12:15:18 +01:00
[EC-499] Add encryptService to domain model decryption (#3385)
Co-authored-by: Matt Gibson <mgibson@bitwarden.com>
This commit is contained in:
parent
063acfef40
commit
cff2422d7f
@ -413,7 +413,7 @@ export default class MainBackground {
|
||||
this.eventService,
|
||||
this.logService
|
||||
);
|
||||
this.containerService = new ContainerService(this.cryptoService);
|
||||
this.containerService = new ContainerService(this.cryptoService, this.encryptService);
|
||||
this.auditService = new AuditService(this.cryptoFunctionService, this.apiService);
|
||||
this.exportService = new ExportService(
|
||||
this.folderService,
|
||||
|
@ -193,7 +193,7 @@ export class Main {
|
||||
|
||||
this.organizationApiService = new OrganizationApiService(this.apiService);
|
||||
|
||||
this.containerService = new ContainerService(this.cryptoService);
|
||||
this.containerService = new ContainerService(this.cryptoService, this.encryptService);
|
||||
|
||||
this.settingsService = new SettingsService(this.stateService);
|
||||
|
||||
|
@ -2,6 +2,7 @@ import { Inject, Injectable } from "@angular/core";
|
||||
|
||||
import { WINDOW } from "@bitwarden/angular/services/jslib-services.module";
|
||||
import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction";
|
||||
import { AbstractEncryptService } from "@bitwarden/common/abstractions/abstractEncrypt.service";
|
||||
import { CryptoService as CryptoServiceAbstraction } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { EnvironmentService as EnvironmentServiceAbstraction } from "@bitwarden/common/abstractions/environment.service";
|
||||
import { EventService as EventServiceAbstraction } from "@bitwarden/common/abstractions/event.service";
|
||||
@ -34,7 +35,8 @@ export class InitService {
|
||||
private stateService: StateServiceAbstraction,
|
||||
private cryptoService: CryptoServiceAbstraction,
|
||||
private nativeMessagingService: NativeMessagingService,
|
||||
private themingService: AbstractThemingService
|
||||
private themingService: AbstractThemingService,
|
||||
private encryptService: AbstractEncryptService
|
||||
) {}
|
||||
|
||||
init() {
|
||||
@ -65,7 +67,7 @@ export class InitService {
|
||||
await this.stateService.setInstalledVersion(currentVersion);
|
||||
}
|
||||
|
||||
const containerService = new ContainerService(this.cryptoService);
|
||||
const containerService = new ContainerService(this.cryptoService, this.encryptService);
|
||||
containerService.attachToGlobal(this.win);
|
||||
};
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import { Inject, Injectable } from "@angular/core";
|
||||
|
||||
import { WINDOW } from "@bitwarden/angular/services/jslib-services.module";
|
||||
import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction";
|
||||
import { AbstractEncryptService } from "@bitwarden/common/abstractions/abstractEncrypt.service";
|
||||
import { CryptoService as CryptoServiceAbstraction } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import {
|
||||
EnvironmentService as EnvironmentServiceAbstraction,
|
||||
@ -31,7 +32,8 @@ export class InitService {
|
||||
private twoFactorService: TwoFactorServiceAbstraction,
|
||||
private stateService: StateServiceAbstraction,
|
||||
private cryptoService: CryptoServiceAbstraction,
|
||||
private themingService: AbstractThemingService
|
||||
private themingService: AbstractThemingService,
|
||||
private encryptService: AbstractEncryptService
|
||||
) {}
|
||||
|
||||
init() {
|
||||
@ -51,7 +53,7 @@ export class InitService {
|
||||
const htmlEl = this.win.document.documentElement;
|
||||
htmlEl.classList.add("locale_" + this.i18nService.translationLocale);
|
||||
await this.themingService.monitorThemeChanges();
|
||||
const containerService = new ContainerService(this.cryptoService);
|
||||
const containerService = new ContainerService(this.cryptoService, this.encryptService);
|
||||
containerService.attachToGlobal(this.win);
|
||||
};
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
import Substitute, { Arg } from "@fluffy-spoon/substitute";
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
|
||||
import { AbstractEncryptService } from "@bitwarden/common/abstractions/abstractEncrypt.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { AttachmentData } from "@bitwarden/common/models/data/attachmentData";
|
||||
import { Attachment } from "@bitwarden/common/models/domain/attachment";
|
||||
import { EncString } from "@bitwarden/common/models/domain/encString";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/models/domain/symmetricCryptoKey";
|
||||
import { ContainerService } from "@bitwarden/common/services/container.service";
|
||||
|
||||
@ -54,30 +56,79 @@ describe("Attachment", () => {
|
||||
expect(attachment.toAttachmentData()).toEqual(data);
|
||||
});
|
||||
|
||||
it("Decrypt", async () => {
|
||||
const attachment = new Attachment();
|
||||
attachment.id = "id";
|
||||
attachment.url = "url";
|
||||
attachment.size = "1100";
|
||||
attachment.sizeName = "1.1 KB";
|
||||
attachment.key = mockEnc("key");
|
||||
attachment.fileName = mockEnc("fileName");
|
||||
describe("decrypt", () => {
|
||||
let cryptoService: MockProxy<CryptoService>;
|
||||
let encryptService: MockProxy<AbstractEncryptService>;
|
||||
|
||||
const cryptoService = Substitute.for<CryptoService>();
|
||||
cryptoService.getOrgKey(null).resolves(null);
|
||||
cryptoService.decryptToBytes(Arg.any(), Arg.any()).resolves(makeStaticByteArray(32));
|
||||
beforeEach(() => {
|
||||
cryptoService = mock<CryptoService>();
|
||||
encryptService = mock<AbstractEncryptService>();
|
||||
|
||||
(window as any).bitwardenContainerService = new ContainerService(cryptoService);
|
||||
(window as any).bitwardenContainerService = new ContainerService(
|
||||
cryptoService,
|
||||
encryptService
|
||||
);
|
||||
});
|
||||
|
||||
const view = await attachment.decrypt(null);
|
||||
it("expected output", async () => {
|
||||
const attachment = new Attachment();
|
||||
attachment.id = "id";
|
||||
attachment.url = "url";
|
||||
attachment.size = "1100";
|
||||
attachment.sizeName = "1.1 KB";
|
||||
attachment.key = mockEnc("key");
|
||||
attachment.fileName = mockEnc("fileName");
|
||||
|
||||
expect(view).toEqual({
|
||||
id: "id",
|
||||
url: "url",
|
||||
size: "1100",
|
||||
sizeName: "1.1 KB",
|
||||
fileName: "fileName",
|
||||
key: expect.any(SymmetricCryptoKey),
|
||||
encryptService.decryptToBytes.mockResolvedValue(makeStaticByteArray(32));
|
||||
|
||||
const view = await attachment.decrypt(null);
|
||||
|
||||
expect(view).toEqual({
|
||||
id: "id",
|
||||
url: "url",
|
||||
size: "1100",
|
||||
sizeName: "1.1 KB",
|
||||
fileName: "fileName",
|
||||
key: expect.any(SymmetricCryptoKey),
|
||||
});
|
||||
});
|
||||
|
||||
describe("decrypts attachment.key", () => {
|
||||
let attachment: Attachment;
|
||||
|
||||
beforeEach(() => {
|
||||
attachment = new Attachment();
|
||||
attachment.key = mock<EncString>();
|
||||
});
|
||||
|
||||
it("uses the provided key without depending on CryptoService", async () => {
|
||||
const providedKey = mock<SymmetricCryptoKey>();
|
||||
|
||||
await attachment.decrypt(null, providedKey);
|
||||
|
||||
expect(cryptoService.getKeyForUserEncryption).not.toHaveBeenCalled();
|
||||
expect(encryptService.decryptToBytes).toHaveBeenCalledWith(attachment.key, providedKey);
|
||||
});
|
||||
|
||||
it("gets an organization key if required", async () => {
|
||||
const orgKey = mock<SymmetricCryptoKey>();
|
||||
cryptoService.getOrgKey.calledWith("orgId").mockResolvedValue(orgKey);
|
||||
|
||||
await attachment.decrypt("orgId", null);
|
||||
|
||||
expect(cryptoService.getOrgKey).toHaveBeenCalledWith("orgId");
|
||||
expect(encryptService.decryptToBytes).toHaveBeenCalledWith(attachment.key, orgKey);
|
||||
});
|
||||
|
||||
it("gets the user's decryption key if required", async () => {
|
||||
const userKey = mock<SymmetricCryptoKey>();
|
||||
cryptoService.getKeyForUserEncryption.mockResolvedValue(userKey);
|
||||
|
||||
await attachment.decrypt(null, null);
|
||||
|
||||
expect(cryptoService.getKeyForUserEncryption).toHaveBeenCalled();
|
||||
expect(encryptService.decryptToBytes).toHaveBeenCalledWith(attachment.key, userKey);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,7 @@
|
||||
import Substitute, { Arg } from "@fluffy-spoon/substitute";
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
|
||||
import { AbstractEncryptService } from "@bitwarden/common/abstractions/abstractEncrypt.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { EncryptionType } from "@bitwarden/common/enums/encryptionType";
|
||||
import { EncString } from "@bitwarden/common/models/domain/encString";
|
||||
@ -48,10 +50,15 @@ describe("EncString", () => {
|
||||
|
||||
const cryptoService = Substitute.for<CryptoService>();
|
||||
cryptoService.getOrgKey(null).resolves(null);
|
||||
cryptoService.decryptToUtf8(encString, Arg.any()).resolves("decrypted");
|
||||
|
||||
const encryptService = Substitute.for<AbstractEncryptService>();
|
||||
encryptService.decryptToUtf8(encString, Arg.any()).resolves("decrypted");
|
||||
|
||||
beforeEach(() => {
|
||||
(window as any).bitwardenContainerService = new ContainerService(cryptoService);
|
||||
(window as any).bitwardenContainerService = new ContainerService(
|
||||
cryptoService,
|
||||
encryptService
|
||||
);
|
||||
});
|
||||
|
||||
it("decrypts correctly", async () => {
|
||||
@ -62,7 +69,7 @@ describe("EncString", () => {
|
||||
|
||||
it("result should be cached", async () => {
|
||||
const decrypted = await encString.decrypt(null);
|
||||
cryptoService.received(1).decryptToUtf8(Arg.any(), Arg.any());
|
||||
encryptService.received(1).decryptToUtf8(Arg.any(), Arg.any());
|
||||
|
||||
expect(decrypted).toBe("decrypted");
|
||||
});
|
||||
@ -148,25 +155,28 @@ describe("EncString", () => {
|
||||
});
|
||||
|
||||
describe("decrypt", () => {
|
||||
it("throws exception when bitwarden container not initialized", async () => {
|
||||
const encString = new EncString(null);
|
||||
let cryptoService: MockProxy<CryptoService>;
|
||||
let encryptService: MockProxy<AbstractEncryptService>;
|
||||
let encString: EncString;
|
||||
|
||||
expect.assertions(1);
|
||||
try {
|
||||
await encString.decrypt(null);
|
||||
} catch (e) {
|
||||
expect(e.message).toEqual("global bitwardenContainerService not initialized.");
|
||||
}
|
||||
beforeEach(() => {
|
||||
cryptoService = mock<CryptoService>();
|
||||
encryptService = mock<AbstractEncryptService>();
|
||||
encString = new EncString(null);
|
||||
|
||||
(window as any).bitwardenContainerService = new ContainerService(
|
||||
cryptoService,
|
||||
encryptService
|
||||
);
|
||||
});
|
||||
|
||||
it("handles value it can't decrypt", async () => {
|
||||
const encString = new EncString(null);
|
||||
encryptService.decryptToUtf8.mockRejectedValue("error");
|
||||
|
||||
const cryptoService = Substitute.for<CryptoService>();
|
||||
cryptoService.getOrgKey(null).resolves(null);
|
||||
cryptoService.decryptToUtf8(encString, Arg.any()).throws("error");
|
||||
|
||||
(window as any).bitwardenContainerService = new ContainerService(cryptoService);
|
||||
(window as any).bitwardenContainerService = new ContainerService(
|
||||
cryptoService,
|
||||
encryptService
|
||||
);
|
||||
|
||||
const decrypted = await encString.decrypt(null);
|
||||
|
||||
@ -178,18 +188,35 @@ describe("EncString", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("passes along key", async () => {
|
||||
const encString = new EncString(null);
|
||||
const key = Substitute.for<SymmetricCryptoKey>();
|
||||
|
||||
const cryptoService = Substitute.for<CryptoService>();
|
||||
cryptoService.getOrgKey(null).resolves(null);
|
||||
|
||||
(window as any).bitwardenContainerService = new ContainerService(cryptoService);
|
||||
it("uses provided key without depending on CryptoService", async () => {
|
||||
const key = mock<SymmetricCryptoKey>();
|
||||
|
||||
await encString.decrypt(null, key);
|
||||
|
||||
cryptoService.received().decryptToUtf8(encString, key);
|
||||
expect(cryptoService.getKeyForUserEncryption).not.toHaveBeenCalled();
|
||||
expect(encryptService.decryptToUtf8).toHaveBeenCalledWith(encString, key);
|
||||
});
|
||||
|
||||
it("gets an organization key if required", async () => {
|
||||
const orgKey = mock<SymmetricCryptoKey>();
|
||||
|
||||
cryptoService.getOrgKey.calledWith("orgId").mockResolvedValue(orgKey);
|
||||
|
||||
await encString.decrypt("orgId", null);
|
||||
|
||||
expect(cryptoService.getOrgKey).toHaveBeenCalledWith("orgId");
|
||||
expect(encryptService.decryptToUtf8).toHaveBeenCalledWith(encString, orgKey);
|
||||
});
|
||||
|
||||
it("gets the user's decryption key if required", async () => {
|
||||
const userKey = mock<SymmetricCryptoKey>();
|
||||
|
||||
cryptoService.getKeyForUserEncryption.mockResolvedValue(userKey);
|
||||
|
||||
await encString.decrypt(null, null);
|
||||
|
||||
expect(cryptoService.getKeyForUserEncryption).toHaveBeenCalledWith();
|
||||
expect(encryptService.decryptToUtf8).toHaveBeenCalledWith(encString, userKey);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import Substitute, { Arg, SubstituteOf } from "@fluffy-spoon/substitute";
|
||||
|
||||
import { AbstractEncryptService } from "@bitwarden/common/abstractions/abstractEncrypt.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { SendType } from "@bitwarden/common/enums/sendType";
|
||||
import { SendData } from "@bitwarden/common/models/data/sendData";
|
||||
@ -110,7 +111,9 @@ describe("Send", () => {
|
||||
cryptoService.decryptToBytes(send.key, null).resolves(makeStaticByteArray(32));
|
||||
cryptoService.makeSendKey(Arg.any()).resolves("cryptoKey" as any);
|
||||
|
||||
(window as any).bitwardenContainerService = new ContainerService(cryptoService);
|
||||
const encryptService = Substitute.for<AbstractEncryptService>();
|
||||
|
||||
(window as any).bitwardenContainerService = new ContainerService(cryptoService, encryptService);
|
||||
|
||||
const view = await send.decrypt();
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute";
|
||||
import { BehaviorSubject, firstValueFrom } from "rxjs";
|
||||
|
||||
import { AbstractEncryptService } from "@bitwarden/common/abstractions/abstractEncrypt.service";
|
||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
@ -15,6 +16,7 @@ describe("Folder Service", () => {
|
||||
let folderService: FolderService;
|
||||
|
||||
let cryptoService: SubstituteOf<CryptoService>;
|
||||
let encryptService: SubstituteOf<AbstractEncryptService>;
|
||||
let i18nService: SubstituteOf<I18nService>;
|
||||
let cipherService: SubstituteOf<CipherService>;
|
||||
let stateService: SubstituteOf<StateService>;
|
||||
@ -23,6 +25,7 @@ describe("Folder Service", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
cryptoService = Substitute.for();
|
||||
encryptService = Substitute.for();
|
||||
i18nService = Substitute.for();
|
||||
cipherService = Substitute.for();
|
||||
stateService = Substitute.for();
|
||||
@ -34,7 +37,7 @@ describe("Folder Service", () => {
|
||||
});
|
||||
stateService.activeAccount$.returns(activeAccount);
|
||||
stateService.activeAccountUnlocked$.returns(activeAccountUnlocked);
|
||||
(window as any).bitwardenContainerService = new ContainerService(cryptoService);
|
||||
(window as any).bitwardenContainerService = new ContainerService(cryptoService, encryptService);
|
||||
|
||||
folderService = new FolderService(cryptoService, i18nService, cipherService, stateService);
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute";
|
||||
import { BehaviorSubject, firstValueFrom } from "rxjs";
|
||||
|
||||
import { AbstractEncryptService } from "@bitwarden/common/abstractions/abstractEncrypt.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { ContainerService } from "@bitwarden/common/services/container.service";
|
||||
import { SettingsService } from "@bitwarden/common/services/settings.service";
|
||||
@ -10,12 +11,14 @@ describe("SettingsService", () => {
|
||||
let settingsService: SettingsService;
|
||||
|
||||
let cryptoService: SubstituteOf<CryptoService>;
|
||||
let encryptService: SubstituteOf<AbstractEncryptService>;
|
||||
let stateService: SubstituteOf<StateService>;
|
||||
let activeAccount: BehaviorSubject<string>;
|
||||
let activeAccountUnlocked: BehaviorSubject<boolean>;
|
||||
|
||||
beforeEach(() => {
|
||||
cryptoService = Substitute.for();
|
||||
encryptService = Substitute.for();
|
||||
stateService = Substitute.for();
|
||||
activeAccount = new BehaviorSubject("123");
|
||||
activeAccountUnlocked = new BehaviorSubject(true);
|
||||
@ -23,7 +26,7 @@ describe("SettingsService", () => {
|
||||
stateService.getSettings().resolves({ equivalentDomains: [["test"], ["domains"]] });
|
||||
stateService.activeAccount$.returns(activeAccount);
|
||||
stateService.activeAccountUnlocked$.returns(activeAccountUnlocked);
|
||||
(window as any).bitwardenContainerService = new ContainerService(cryptoService);
|
||||
(window as any).bitwardenContainerService = new ContainerService(cryptoService, encryptService);
|
||||
|
||||
settingsService = new SettingsService(stateService);
|
||||
});
|
||||
|
@ -3,6 +3,7 @@ import * as tldjs from "tldjs";
|
||||
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
|
||||
import { AbstractEncryptService } from "../abstractions/abstractEncrypt.service";
|
||||
import { I18nService } from "../abstractions/i18n.service";
|
||||
|
||||
const nodeURL = typeof window === "undefined" ? require("url") : null;
|
||||
@ -14,6 +15,7 @@ declare global {
|
||||
|
||||
interface BitwardenContainerService {
|
||||
getCryptoService: () => CryptoService;
|
||||
getEncryptService: () => AbstractEncryptService;
|
||||
}
|
||||
|
||||
export class Utils {
|
||||
@ -368,6 +370,16 @@ export class Utils {
|
||||
return s.charAt(0).toUpperCase() + s.slice(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Will throw an error if the ContainerService has not been attached to the window object
|
||||
*/
|
||||
static getContainerService(): BitwardenContainerService {
|
||||
if (this.global.bitwardenContainerService == null) {
|
||||
throw new Error("global bitwardenContainerService not initialized.");
|
||||
}
|
||||
return this.global.bitwardenContainerService;
|
||||
}
|
||||
|
||||
private static validIpAddress(ipString: string): boolean {
|
||||
const ipRegex =
|
||||
/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { CryptoService } from "../../abstractions/crypto.service";
|
||||
import { Utils } from "../../misc/utils";
|
||||
import { AttachmentData } from "../data/attachmentData";
|
||||
import { AttachmentView } from "../view/attachmentView";
|
||||
@ -47,26 +46,33 @@ export class Attachment extends Domain {
|
||||
);
|
||||
|
||||
if (this.key != null) {
|
||||
let cryptoService: CryptoService;
|
||||
const containerService = Utils.global.bitwardenContainerService;
|
||||
if (containerService) {
|
||||
cryptoService = containerService.getCryptoService();
|
||||
} else {
|
||||
throw new Error("global bitwardenContainerService not initialized.");
|
||||
}
|
||||
|
||||
try {
|
||||
const orgKey = await cryptoService.getOrgKey(orgId);
|
||||
const decValue = await cryptoService.decryptToBytes(this.key, orgKey ?? encKey);
|
||||
view.key = new SymmetricCryptoKey(decValue);
|
||||
} catch (e) {
|
||||
// TODO: error?
|
||||
}
|
||||
view.key = await this.decryptAttachmentKey(orgId, encKey);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private async decryptAttachmentKey(orgId: string, encKey?: SymmetricCryptoKey) {
|
||||
try {
|
||||
if (encKey == null) {
|
||||
encKey = await this.getKeyForDecryption(orgId);
|
||||
}
|
||||
|
||||
const encryptService = Utils.getContainerService().getEncryptService();
|
||||
const decValue = await encryptService.decryptToBytes(this.key, encKey);
|
||||
return new SymmetricCryptoKey(decValue);
|
||||
} catch (e) {
|
||||
// TODO: error?
|
||||
}
|
||||
}
|
||||
|
||||
private async getKeyForDecryption(orgId: string) {
|
||||
const cryptoService = Utils.getContainerService().getCryptoService();
|
||||
return orgId != null
|
||||
? await cryptoService.getOrgKey(orgId)
|
||||
: await cryptoService.getKeyForUserEncryption();
|
||||
}
|
||||
|
||||
toAttachmentData(): AttachmentData {
|
||||
const a = new AttachmentData();
|
||||
a.size = this.size;
|
||||
|
@ -2,7 +2,6 @@ import { Jsonify } from "type-fest";
|
||||
|
||||
import { IEncrypted } from "@bitwarden/common/interfaces/IEncrypted";
|
||||
|
||||
import { CryptoService } from "../../abstractions/crypto.service";
|
||||
import { EncryptionType } from "../../enums/encryptionType";
|
||||
import { Utils } from "../../misc/utils";
|
||||
|
||||
@ -29,30 +28,6 @@ export class EncString implements IEncrypted {
|
||||
}
|
||||
}
|
||||
|
||||
async decrypt(orgId: string, key: SymmetricCryptoKey = null): Promise<string> {
|
||||
if (this.decryptedValue != null) {
|
||||
return this.decryptedValue;
|
||||
}
|
||||
|
||||
let cryptoService: CryptoService;
|
||||
const containerService = Utils.global.bitwardenContainerService;
|
||||
if (containerService) {
|
||||
cryptoService = containerService.getCryptoService();
|
||||
} else {
|
||||
throw new Error("global bitwardenContainerService not initialized.");
|
||||
}
|
||||
|
||||
try {
|
||||
if (key == null) {
|
||||
key = await cryptoService.getOrgKey(orgId);
|
||||
}
|
||||
this.decryptedValue = await cryptoService.decryptToUtf8(this, key);
|
||||
} catch (e) {
|
||||
this.decryptedValue = "[error: cannot decrypt]";
|
||||
}
|
||||
return this.decryptedValue;
|
||||
}
|
||||
|
||||
get ivBytes(): ArrayBuffer {
|
||||
return this.iv == null ? null : Utils.fromB64ToArray(this.iv).buffer;
|
||||
}
|
||||
@ -160,4 +135,32 @@ export class EncString implements IEncrypted {
|
||||
encPieces,
|
||||
};
|
||||
}
|
||||
|
||||
async decrypt(orgId: string, key: SymmetricCryptoKey = null): Promise<string> {
|
||||
if (this.decryptedValue != null) {
|
||||
return this.decryptedValue;
|
||||
}
|
||||
|
||||
try {
|
||||
if (key == null) {
|
||||
key = await this.getKeyForDecryption(orgId);
|
||||
}
|
||||
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);
|
||||
} catch (e) {
|
||||
this.decryptedValue = "[error: cannot decrypt]";
|
||||
}
|
||||
return this.decryptedValue;
|
||||
}
|
||||
|
||||
private async getKeyForDecryption(orgId: string) {
|
||||
const cryptoService = Utils.getContainerService().getCryptoService();
|
||||
return orgId != null
|
||||
? await cryptoService.getOrgKey(orgId)
|
||||
: await cryptoService.getKeyForUserEncryption();
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { CryptoService } from "../../abstractions/crypto.service";
|
||||
import { SendType } from "../../enums/sendType";
|
||||
import { Utils } from "../../misc/utils";
|
||||
import { SendData } from "../data/sendData";
|
||||
@ -71,13 +70,7 @@ export class Send extends Domain {
|
||||
async decrypt(): Promise<SendView> {
|
||||
const model = new SendView(this);
|
||||
|
||||
let cryptoService: CryptoService;
|
||||
const containerService = Utils.global.bitwardenContainerService;
|
||||
if (containerService) {
|
||||
cryptoService = containerService.getCryptoService();
|
||||
} else {
|
||||
throw new Error("global bitwardenContainerService not initialized.");
|
||||
}
|
||||
const cryptoService = Utils.getContainerService().getCryptoService();
|
||||
|
||||
try {
|
||||
model.key = await cryptoService.decryptToBytes(this.key, null);
|
||||
|
@ -1,7 +1,11 @@
|
||||
import { AbstractEncryptService } from "../abstractions/abstractEncrypt.service";
|
||||
import { CryptoService } from "../abstractions/crypto.service";
|
||||
|
||||
export class ContainerService {
|
||||
constructor(private cryptoService: CryptoService) {}
|
||||
constructor(
|
||||
private cryptoService: CryptoService,
|
||||
private encryptService: AbstractEncryptService
|
||||
) {}
|
||||
|
||||
attachToGlobal(global: any) {
|
||||
if (!global.bitwardenContainerService) {
|
||||
@ -9,7 +13,23 @@ export class ContainerService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Will throw if CryptoService was not instantiated and provided to the ContainerService constructor
|
||||
*/
|
||||
getCryptoService(): CryptoService {
|
||||
if (this.cryptoService == null) {
|
||||
throw new Error("ContainerService.cryptoService not initialized.");
|
||||
}
|
||||
return this.cryptoService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Will throw if EncryptService was not instantiated and provided to the ContainerService constructor
|
||||
*/
|
||||
getEncryptService(): AbstractEncryptService {
|
||||
if (this.encryptService == null) {
|
||||
throw new Error("ContainerService.encryptService not initialized.");
|
||||
}
|
||||
return this.encryptService;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user