mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 08:13:42 +00:00
[PM-11477] Remove deprecated cryptoservice functions (#10854)
* Remove deprecated cryptoservice functions * Use getUserkeyWithLegacySupport to get userkey * Fix tests * Fix tests * Fix tests * Remove unused cryptoservice instances * Fix build * Remove unused apiService in constructor * Fix encryption * Ensure passed in key is used if present * Fix sends and folders * Fix tests * Remove logged key * Fix import for account restricted keys
This commit is contained in:
@@ -15,7 +15,7 @@ export abstract class FolderService implements UserKeyRotationDataProvider<Folde
|
||||
folderViews$: Observable<FolderView[]>;
|
||||
|
||||
clearCache: () => Promise<void>;
|
||||
encrypt: (model: FolderView, key?: SymmetricCryptoKey) => Promise<Folder>;
|
||||
encrypt: (model: FolderView, key: SymmetricCryptoKey) => Promise<Folder>;
|
||||
get: (id: string) => Promise<Folder>;
|
||||
getDecrypted$: (id: string) => Observable<FolderView | undefined>;
|
||||
getAllFromState: () => Promise<Folder[]>;
|
||||
|
||||
@@ -145,6 +145,7 @@ describe("Cipher Service", () => {
|
||||
cipherFileUploadService,
|
||||
configService,
|
||||
stateProvider,
|
||||
accountService,
|
||||
);
|
||||
|
||||
cipherObj = new Cipher(cipherData);
|
||||
@@ -273,7 +274,7 @@ describe("Cipher Service", () => {
|
||||
cryptoService.makeCipherKey.mockReturnValue(
|
||||
Promise.resolve(new SymmetricCryptoKey(makeStaticByteArray(64)) as CipherKey),
|
||||
);
|
||||
cryptoService.encrypt.mockImplementation(encryptText);
|
||||
encryptService.encrypt.mockImplementation(encryptText);
|
||||
|
||||
jest.spyOn(cipherService as any, "getAutofillOnPageLoadDefault").mockResolvedValue(true);
|
||||
});
|
||||
@@ -285,6 +286,10 @@ describe("Cipher Service", () => {
|
||||
{ uri: "uri", match: UriMatchStrategy.RegularExpression } as LoginUriView,
|
||||
];
|
||||
|
||||
cryptoService.getOrgKey.mockReturnValue(
|
||||
Promise.resolve<any>(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey),
|
||||
);
|
||||
|
||||
const domain = await cipherService.encrypt(cipherView, userId);
|
||||
|
||||
expect(domain.login.uris).toEqual([
|
||||
@@ -301,6 +306,9 @@ describe("Cipher Service", () => {
|
||||
it("is null when feature flag is false", async () => {
|
||||
configService.getFeatureFlag.mockResolvedValue(false);
|
||||
|
||||
cryptoService.getOrgKey.mockReturnValue(
|
||||
Promise.resolve<any>(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey),
|
||||
);
|
||||
const cipher = await cipherService.encrypt(cipherView, userId);
|
||||
|
||||
expect(cipher.key).toBeNull();
|
||||
@@ -322,6 +330,9 @@ describe("Cipher Service", () => {
|
||||
|
||||
it("is not called when feature flag is false", async () => {
|
||||
configService.getFeatureFlag.mockResolvedValue(false);
|
||||
cryptoService.getOrgKey.mockReturnValue(
|
||||
Promise.resolve<any>(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey),
|
||||
);
|
||||
|
||||
await cipherService.encrypt(cipherView, userId);
|
||||
|
||||
@@ -330,6 +341,9 @@ describe("Cipher Service", () => {
|
||||
|
||||
it("is called when feature flag is true", async () => {
|
||||
configService.getFeatureFlag.mockResolvedValue(true);
|
||||
cryptoService.getOrgKey.mockReturnValue(
|
||||
Promise.resolve<any>(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey),
|
||||
);
|
||||
|
||||
await cipherService.encrypt(cipherView, userId);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { firstValueFrom, map, Observable, skipWhile, switchMap } from "rxjs";
|
||||
import { SemVer } from "semver";
|
||||
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { BulkEncryptService } from "@bitwarden/common/platform/abstractions/bulk-encrypt.service";
|
||||
|
||||
@@ -108,6 +109,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
private cipherFileUploadService: CipherFileUploadService,
|
||||
private configService: ConfigService,
|
||||
private stateProvider: StateProvider,
|
||||
private accountService: AccountService,
|
||||
) {
|
||||
this.localDataState = this.stateProvider.getActive(LOCAL_DATA_KEY);
|
||||
this.encryptedCiphersState = this.stateProvider.getActive(ENCRYPTED_CIPHERS);
|
||||
@@ -165,7 +167,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
async encrypt(
|
||||
model: CipherView,
|
||||
userId: UserId,
|
||||
keyForEncryption?: SymmetricCryptoKey,
|
||||
keyForCipherEncryption?: SymmetricCryptoKey,
|
||||
keyForCipherKeyDecryption?: SymmetricCryptoKey,
|
||||
originalCipher: Cipher = null,
|
||||
): Promise<Cipher> {
|
||||
@@ -195,26 +197,21 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
const userOrOrgKey = await this.getKeyForCipherKeyDecryption(cipher, userId);
|
||||
// The keyForEncryption is only used for encrypting the cipher key, not the cipher itself, since cipher key encryption is enabled.
|
||||
// If the caller has provided a key for cipher key encryption, use it. Otherwise, use the user or org key.
|
||||
keyForEncryption ||= userOrOrgKey;
|
||||
keyForCipherEncryption ||= userOrOrgKey;
|
||||
// If the caller has provided a key for cipher key decryption, use it. Otherwise, use the user or org key.
|
||||
keyForCipherKeyDecryption ||= userOrOrgKey;
|
||||
return this.encryptCipherWithCipherKey(
|
||||
model,
|
||||
cipher,
|
||||
keyForEncryption,
|
||||
keyForCipherEncryption,
|
||||
keyForCipherKeyDecryption,
|
||||
);
|
||||
} else {
|
||||
if (keyForEncryption == null && cipher.organizationId != null) {
|
||||
keyForEncryption = await this.cryptoService.getOrgKey(cipher.organizationId);
|
||||
if (keyForEncryption == null) {
|
||||
throw new Error("Cannot encrypt cipher for organization. No key.");
|
||||
}
|
||||
}
|
||||
keyForCipherEncryption ||= await this.getKeyForCipherKeyDecryption(cipher, userId);
|
||||
// We want to ensure that the cipher key is null if cipher key encryption is disabled
|
||||
// so that decryption uses the proper key.
|
||||
cipher.key = null;
|
||||
return this.encryptCipher(model, cipher, keyForEncryption);
|
||||
return this.encryptCipher(model, cipher, keyForCipherEncryption);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,7 +240,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
key,
|
||||
).then(async () => {
|
||||
if (model.key != null) {
|
||||
attachment.key = await this.cryptoService.encrypt(model.key.key, key);
|
||||
attachment.key = await this.encryptService.encrypt(model.key.key, key);
|
||||
}
|
||||
encAttachments.push(attachment);
|
||||
});
|
||||
@@ -1348,7 +1345,9 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
}
|
||||
|
||||
const encBuf = await EncArrayBuffer.fromResponse(attachmentResponse);
|
||||
const decBuf = await this.cryptoService.decryptFromBytes(encBuf, null);
|
||||
const activeUserId = await firstValueFrom(this.accountService.activeAccount$);
|
||||
const userKey = await this.cryptoService.getUserKeyWithLegacySupport(activeUserId.id);
|
||||
const decBuf = await this.encryptService.decryptToBytes(encBuf, userKey);
|
||||
|
||||
let encKey: UserKey | OrgKey;
|
||||
encKey = await this.cryptoService.getOrgKey(organizationId);
|
||||
@@ -1412,7 +1411,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
.then(() => {
|
||||
const modelProp = (model as any)[map[theProp] || theProp];
|
||||
if (modelProp && modelProp !== "") {
|
||||
return self.cryptoService.encrypt(modelProp, key);
|
||||
return self.encryptService.encrypt(modelProp, key);
|
||||
}
|
||||
return null;
|
||||
})
|
||||
@@ -1458,7 +1457,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
key,
|
||||
);
|
||||
const uriHash = await this.encryptService.hash(model.login.uris[i].uri, "sha256");
|
||||
loginUri.uriChecksum = await this.cryptoService.encrypt(uriHash, key);
|
||||
loginUri.uriChecksum = await this.encryptService.encrypt(uriHash, key);
|
||||
cipher.login.uris.push(loginUri);
|
||||
}
|
||||
}
|
||||
@@ -1485,8 +1484,8 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
},
|
||||
key,
|
||||
);
|
||||
domainKey.counter = await this.cryptoService.encrypt(String(viewKey.counter), key);
|
||||
domainKey.discoverable = await this.cryptoService.encrypt(
|
||||
domainKey.counter = await this.encryptService.encrypt(String(viewKey.counter), key);
|
||||
domainKey.discoverable = await this.encryptService.encrypt(
|
||||
String(viewKey.discoverable),
|
||||
key,
|
||||
);
|
||||
@@ -1605,11 +1604,23 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
this.sortedCiphersCache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a cipher object.
|
||||
* @param model The cipher view model.
|
||||
* @param cipher The cipher object.
|
||||
* @param key The encryption key to encrypt with. This can be the org key, user key or cipher key, but must never be null
|
||||
*/
|
||||
private async encryptCipher(
|
||||
model: CipherView,
|
||||
cipher: Cipher,
|
||||
key: SymmetricCryptoKey,
|
||||
): Promise<Cipher> {
|
||||
if (key == null) {
|
||||
throw new Error(
|
||||
"Key to encrypt cipher must not be null. Use the org key, user key or cipher key.",
|
||||
);
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
this.encryptObjProperty(
|
||||
model,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { firstValueFrom, map, Observable } from "rxjs";
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
|
||||
|
||||
import { CryptoService } from "../../platform/abstractions/crypto.service";
|
||||
import { I18nService } from "../../platform/abstractions/i18n.service";
|
||||
import { Utils } from "../../platform/misc/utils";
|
||||
@@ -61,6 +63,7 @@ export class CollectionService implements CollectionServiceAbstraction {
|
||||
|
||||
constructor(
|
||||
private cryptoService: CryptoService,
|
||||
private encryptService: EncryptService,
|
||||
private i18nService: I18nService,
|
||||
protected stateProvider: StateProvider,
|
||||
) {
|
||||
@@ -101,7 +104,7 @@ export class CollectionService implements CollectionServiceAbstraction {
|
||||
collection.organizationId = model.organizationId;
|
||||
collection.readOnly = model.readOnly;
|
||||
collection.externalId = model.externalId;
|
||||
collection.name = await this.cryptoService.encrypt(model.name, key);
|
||||
collection.name = await this.encryptService.encrypt(model.name, key);
|
||||
return collection;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,13 @@ describe("Folder Service", () => {
|
||||
);
|
||||
encryptService.decryptToUtf8.mockResolvedValue("DEC");
|
||||
|
||||
folderService = new FolderService(cryptoService, i18nService, cipherService, stateProvider);
|
||||
folderService = new FolderService(
|
||||
cryptoService,
|
||||
encryptService,
|
||||
i18nService,
|
||||
cipherService,
|
||||
stateProvider,
|
||||
);
|
||||
|
||||
folderState = stateProvider.activeUser.getFake(FOLDER_ENCRYPTED_FOLDERS);
|
||||
|
||||
@@ -62,9 +68,9 @@ describe("Folder Service", () => {
|
||||
model.id = "2";
|
||||
model.name = "Test Folder";
|
||||
|
||||
cryptoService.encrypt.mockResolvedValue(new EncString("ENC"));
|
||||
encryptService.encrypt.mockResolvedValue(new EncString("ENC"));
|
||||
|
||||
const result = await folderService.encrypt(model);
|
||||
const result = await folderService.encrypt(model, null);
|
||||
|
||||
expect(result).toEqual({
|
||||
id: "2",
|
||||
@@ -185,7 +191,7 @@ describe("Folder Service", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
encryptedKey = new EncString("Re-encrypted Folder");
|
||||
cryptoService.encrypt.mockResolvedValue(encryptedKey);
|
||||
encryptService.encrypt.mockResolvedValue(encryptedKey);
|
||||
});
|
||||
|
||||
it("returns re-encrypted user folders", async () => {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { Observable, firstValueFrom, map, shareReplay } from "rxjs";
|
||||
|
||||
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
|
||||
|
||||
import { CryptoService } from "../../../platform/abstractions/crypto.service";
|
||||
import { I18nService } from "../../../platform/abstractions/i18n.service";
|
||||
import { Utils } from "../../../platform/misc/utils";
|
||||
@@ -25,6 +27,7 @@ export class FolderService implements InternalFolderServiceAbstraction {
|
||||
|
||||
constructor(
|
||||
private cryptoService: CryptoService,
|
||||
private encryptService: EncryptService,
|
||||
private i18nService: I18nService,
|
||||
private cipherService: CipherService,
|
||||
private stateProvider: StateProvider,
|
||||
@@ -48,10 +51,10 @@ export class FolderService implements InternalFolderServiceAbstraction {
|
||||
}
|
||||
|
||||
// TODO: This should be moved to EncryptService or something
|
||||
async encrypt(model: FolderView, key?: SymmetricCryptoKey): Promise<Folder> {
|
||||
async encrypt(model: FolderView, key: SymmetricCryptoKey): Promise<Folder> {
|
||||
const folder = new Folder();
|
||||
folder.id = model.id;
|
||||
folder.name = await this.cryptoService.encrypt(model.name, key);
|
||||
folder.name = await this.encryptService.encrypt(model.name, key);
|
||||
return folder;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user