mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-23 16:38:45 +01:00
[PS-2264] Make password protected exports support account's iterations and argon2 (#4479)
* Fix encrypted export using fixed PBKDF2 iterations * Replace hardcoded KdfType in importer * Clean up kdf handling in password-protected export * Extract BitwardenPasswordProtectedFileFormat * Rename bitwarden-json-types * Move StateService import to fix linting issue * Make linter happy * Use abstraction instead of implementation --------- Co-authored-by: Daniel James Smith <djsmith@web.de>
This commit is contained in:
parent
1c88465316
commit
1f472ea309
@ -466,7 +466,8 @@ export default class MainBackground {
|
||||
this.cipherService,
|
||||
this.apiService,
|
||||
this.cryptoService,
|
||||
this.cryptoFunctionService
|
||||
this.cryptoFunctionService,
|
||||
this.stateService
|
||||
);
|
||||
this.notificationsService = new NotificationsService(
|
||||
this.syncService,
|
||||
|
@ -378,7 +378,8 @@ export class Main {
|
||||
this.cipherService,
|
||||
this.apiService,
|
||||
this.cryptoService,
|
||||
this.cryptoFunctionService
|
||||
this.cryptoFunctionService,
|
||||
this.stateService
|
||||
);
|
||||
|
||||
this.auditService = new AuditService(this.cryptoFunctionService, this.apiService);
|
||||
|
@ -472,6 +472,7 @@ import { AbstractThemingService } from "./theming/theming.service.abstraction";
|
||||
ApiServiceAbstraction,
|
||||
CryptoServiceAbstraction,
|
||||
CryptoFunctionServiceAbstraction,
|
||||
StateServiceAbstraction,
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -9,6 +9,7 @@ import { Utils } from "@bitwarden/common/misc/utils";
|
||||
import { EncString } from "@bitwarden/common/models/domain/enc-string";
|
||||
import { CipherWithIdExport as CipherExport } from "@bitwarden/common/models/export/cipher-with-ids.export";
|
||||
import { ExportService } from "@bitwarden/common/services/export.service";
|
||||
import { StateService } from "@bitwarden/common/services/state.service";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
|
||||
@ -144,6 +145,7 @@ describe("ExportService", () => {
|
||||
let cipherService: SubstituteOf<CipherService>;
|
||||
let folderService: SubstituteOf<FolderService>;
|
||||
let cryptoService: SubstituteOf<CryptoService>;
|
||||
let stateService: SubstituteOf<StateService>;
|
||||
|
||||
beforeEach(() => {
|
||||
apiService = Substitute.for<ApiService>();
|
||||
@ -160,7 +162,8 @@ describe("ExportService", () => {
|
||||
cipherService,
|
||||
apiService,
|
||||
cryptoService,
|
||||
cryptoFunctionService
|
||||
cryptoFunctionService,
|
||||
stateService
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
import * as papa from "papaparse";
|
||||
|
||||
import { BitwardenPasswordProtectedFileFormat } from "@bitwarden/importer/src/importers/bitwarden/bitwarden-password-protected-types";
|
||||
|
||||
import { ApiService } from "../abstractions/api.service";
|
||||
import { CryptoService } from "../abstractions/crypto.service";
|
||||
import { CryptoFunctionService } from "../abstractions/cryptoFunction.service";
|
||||
@ -7,12 +9,13 @@ import {
|
||||
ExportFormat,
|
||||
ExportService as ExportServiceAbstraction,
|
||||
} from "../abstractions/export.service";
|
||||
import { StateService } from "../abstractions/state.service";
|
||||
import { CollectionData } from "../admin-console/models/data/collection.data";
|
||||
import { Collection } from "../admin-console/models/domain/collection";
|
||||
import { CollectionDetailsResponse } from "../admin-console/models/response/collection.response";
|
||||
import { CollectionView } from "../admin-console/models/view/collection.view";
|
||||
import { KdfConfig } from "../auth/models/domain/kdf-config";
|
||||
import { DEFAULT_PBKDF2_ITERATIONS, KdfType } from "../enums/kdfType";
|
||||
import { KdfType } from "../enums/kdfType";
|
||||
import { Utils } from "../misc/utils";
|
||||
import { CipherWithIdExport as CipherExport } from "../models/export/cipher-with-ids.export";
|
||||
import { CollectionWithIdExport as CollectionExport } from "../models/export/collection-with-id.export";
|
||||
@ -34,7 +37,8 @@ export class ExportService implements ExportServiceAbstraction {
|
||||
private cipherService: CipherService,
|
||||
private apiService: ApiService,
|
||||
private cryptoService: CryptoService,
|
||||
private cryptoFunctionService: CryptoFunctionService
|
||||
private cryptoFunctionService: CryptoFunctionService,
|
||||
private stateService: StateService
|
||||
) {}
|
||||
|
||||
async getExport(format: ExportFormat = "csv", organizationId?: string): Promise<string> {
|
||||
@ -54,24 +58,23 @@ export class ExportService implements ExportServiceAbstraction {
|
||||
? await this.getOrganizationExport(organizationId, "json")
|
||||
: await this.getExport("json");
|
||||
|
||||
const kdfType: KdfType = await this.stateService.getKdfType();
|
||||
const kdfConfig: KdfConfig = await this.stateService.getKdfConfig();
|
||||
|
||||
const salt = Utils.fromBufferToB64(await this.cryptoFunctionService.randomBytes(16));
|
||||
const kdfConfig = new KdfConfig(DEFAULT_PBKDF2_ITERATIONS);
|
||||
const key = await this.cryptoService.makePinKey(
|
||||
password,
|
||||
salt,
|
||||
KdfType.PBKDF2_SHA256,
|
||||
kdfConfig
|
||||
);
|
||||
const key = await this.cryptoService.makePinKey(password, salt, kdfType, kdfConfig);
|
||||
|
||||
const encKeyValidation = await this.cryptoService.encrypt(Utils.newGuid(), key);
|
||||
const encText = await this.cryptoService.encrypt(clearText, key);
|
||||
|
||||
const jsonDoc: any = {
|
||||
const jsonDoc: BitwardenPasswordProtectedFileFormat = {
|
||||
encrypted: true,
|
||||
passwordProtected: true,
|
||||
salt: salt,
|
||||
kdfType: kdfType,
|
||||
kdfIterations: kdfConfig.iterations,
|
||||
kdfType: KdfType.PBKDF2_SHA256,
|
||||
kdfMemory: kdfConfig.memory,
|
||||
kdfParallelism: kdfConfig.parallelism,
|
||||
encKeyValidation_DO_NOT_EDIT: encKeyValidation.encryptedString,
|
||||
data: encText.encryptedString,
|
||||
};
|
||||
|
@ -9,17 +9,7 @@ import { ImportResult } from "../../models/import-result";
|
||||
import { Importer } from "../importer";
|
||||
|
||||
import { BitwardenJsonImporter } from "./bitwarden-json-importer";
|
||||
|
||||
interface BitwardenPasswordProtectedFileFormat {
|
||||
encrypted: boolean;
|
||||
passwordProtected: boolean;
|
||||
salt: string;
|
||||
kdfIterations: number;
|
||||
kdfType: number;
|
||||
encKeyValidation_DO_NOT_EDIT: string;
|
||||
data: string;
|
||||
}
|
||||
|
||||
import { BitwardenPasswordProtectedFileFormat } from "./bitwarden-password-protected-types";
|
||||
export class BitwardenPasswordProtectedImporter extends BitwardenJsonImporter implements Importer {
|
||||
private key: SymmetricCryptoKey;
|
||||
|
||||
@ -50,8 +40,8 @@ export class BitwardenPasswordProtectedImporter extends BitwardenJsonImporter im
|
||||
this.key = await this.cryptoService.makePinKey(
|
||||
this.password,
|
||||
jdoc.salt,
|
||||
KdfType.PBKDF2_SHA256,
|
||||
new KdfConfig(jdoc.kdfIterations)
|
||||
jdoc.kdfType,
|
||||
new KdfConfig(jdoc.kdfIterations, jdoc.kdfMemory, jdoc.kdfParallelism)
|
||||
);
|
||||
|
||||
const encKeyValidation = new EncString(jdoc.encKeyValidation_DO_NOT_EDIT);
|
||||
|
@ -0,0 +1,11 @@
|
||||
export interface BitwardenPasswordProtectedFileFormat {
|
||||
encrypted: boolean;
|
||||
passwordProtected: boolean;
|
||||
salt: string;
|
||||
kdfIterations: number;
|
||||
kdfMemory?: number;
|
||||
kdfParallelism?: number;
|
||||
kdfType: number;
|
||||
encKeyValidation_DO_NOT_EDIT: string;
|
||||
data: string;
|
||||
}
|
Loading…
Reference in New Issue
Block a user