From 0add2949c0694de9eacd381319540209e7b1f121 Mon Sep 17 00:00:00 2001 From: Jake Fink Date: Tue, 25 Jun 2024 08:21:02 -0400 Subject: [PATCH] [PM-8772] move ranges to static properties on class (#9567) * move ranges to static properties on class * rename static properties --- .../change-kdf/change-kdf.component.ts | 18 +++------ .../services/vault-banners.service.ts | 5 ++- .../src/auth/components/register.component.ts | 2 +- .../auth/components/set-password.component.ts | 3 +- .../src/auth/models/domain/kdf-config.ts | 39 ++++++++++--------- .../auth/services/kdf-config.service.spec.ts | 14 ++----- .../src/platform/enums/kdf-type.enum.ts | 11 ------ .../services/key-generation.service.ts | 18 +++------ .../individual-vault-export.service.spec.ts | 8 +++- .../src/services/vault-export.service.spec.ts | 8 +++- 10 files changed, 54 insertions(+), 72 deletions(-) diff --git a/apps/web/src/app/auth/settings/security/change-kdf/change-kdf.component.ts b/apps/web/src/app/auth/settings/security/change-kdf/change-kdf.component.ts index e9b35dd33d..58553ba198 100644 --- a/apps/web/src/app/auth/settings/security/change-kdf/change-kdf.component.ts +++ b/apps/web/src/app/auth/settings/security/change-kdf/change-kdf.component.ts @@ -5,17 +5,11 @@ import { Subject, takeUntil } from "rxjs"; import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service"; import { Argon2KdfConfig, + DEFAULT_KDF_CONFIG, KdfConfig, PBKDF2KdfConfig, } from "@bitwarden/common/auth/models/domain/kdf-config"; -import { - DEFAULT_KDF_CONFIG, - PBKDF2_ITERATIONS, - ARGON2_ITERATIONS, - ARGON2_MEMORY, - ARGON2_PARALLELISM, - KdfType, -} from "@bitwarden/common/platform/enums"; +import { KdfType } from "@bitwarden/common/platform/enums"; import { DialogService } from "@bitwarden/components"; import { ChangeKdfConfirmationComponent } from "./change-kdf-confirmation.component"; @@ -56,10 +50,10 @@ export class ChangeKdfComponent implements OnInit { }); // Default values for template - protected PBKDF2_ITERATIONS = PBKDF2_ITERATIONS; - protected ARGON2_ITERATIONS = ARGON2_ITERATIONS; - protected ARGON2_MEMORY = ARGON2_MEMORY; - protected ARGON2_PARALLELISM = ARGON2_PARALLELISM; + protected PBKDF2_ITERATIONS = PBKDF2KdfConfig.ITERATIONS; + protected ARGON2_ITERATIONS = Argon2KdfConfig.ITERATIONS; + protected ARGON2_MEMORY = Argon2KdfConfig.MEMORY; + protected ARGON2_PARALLELISM = Argon2KdfConfig.PARALLELISM; constructor( private dialogService: DialogService, diff --git a/apps/web/src/app/vault/individual-vault/vault-banners/services/vault-banners.service.ts b/apps/web/src/app/vault/individual-vault/vault-banners/services/vault-banners.service.ts index 1cb8e13cb3..172d81c48a 100644 --- a/apps/web/src/app/vault/individual-vault/vault-banners/services/vault-banners.service.ts +++ b/apps/web/src/app/vault/individual-vault/vault-banners/services/vault-banners.service.ts @@ -5,9 +5,10 @@ import { mergeMap, take } from "rxjs/operators"; import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service"; import { TokenService } from "@bitwarden/common/auth/abstractions/token.service"; import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction"; +import { PBKDF2KdfConfig } from "@bitwarden/common/auth/models/domain/kdf-config"; import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; -import { KdfType, PBKDF2_ITERATIONS } from "@bitwarden/common/platform/enums"; +import { KdfType } from "@bitwarden/common/platform/enums"; import { StateProvider, ActiveUserState, @@ -200,7 +201,7 @@ export class VaultBannersService { const kdfConfig = await this.kdfConfigService.getKdfConfig(); return ( kdfConfig.kdfType === KdfType.PBKDF2_SHA256 && - kdfConfig.iterations < PBKDF2_ITERATIONS.defaultValue + kdfConfig.iterations < PBKDF2KdfConfig.ITERATIONS.defaultValue ); } diff --git a/libs/angular/src/auth/components/register.component.ts b/libs/angular/src/auth/components/register.component.ts index e3197355dc..533920d13c 100644 --- a/libs/angular/src/auth/components/register.component.ts +++ b/libs/angular/src/auth/components/register.component.ts @@ -5,6 +5,7 @@ import { Router } from "@angular/router"; import { LoginStrategyServiceAbstraction, PasswordLoginCredentials } from "@bitwarden/auth/common"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { AuditService } from "@bitwarden/common/abstractions/audit.service"; +import { DEFAULT_KDF_CONFIG } from "@bitwarden/common/auth/models/domain/kdf-config"; import { RegisterResponse } from "@bitwarden/common/auth/models/response/register.response"; import { KeysRequest } from "@bitwarden/common/models/request/keys.request"; import { ReferenceEventRequest } from "@bitwarden/common/models/request/reference-event.request"; @@ -15,7 +16,6 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; -import { DEFAULT_KDF_CONFIG } from "@bitwarden/common/platform/enums"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password"; import { DialogService } from "@bitwarden/components"; diff --git a/libs/angular/src/auth/components/set-password.component.ts b/libs/angular/src/auth/components/set-password.component.ts index 73c38c8ddb..b08c796753 100644 --- a/libs/angular/src/auth/components/set-password.component.ts +++ b/libs/angular/src/auth/components/set-password.component.ts @@ -17,6 +17,7 @@ import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction"; import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction"; import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason"; +import { DEFAULT_KDF_CONFIG } from "@bitwarden/common/auth/models/domain/kdf-config"; import { SetPasswordRequest } from "@bitwarden/common/auth/models/request/set-password.request"; import { KeysRequest } from "@bitwarden/common/models/request/keys.request"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; @@ -24,7 +25,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; -import { HashPurpose, DEFAULT_KDF_CONFIG } from "@bitwarden/common/platform/enums"; +import { HashPurpose } from "@bitwarden/common/platform/enums"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { EncString } from "@bitwarden/common/platform/models/domain/enc-string"; import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password"; diff --git a/libs/common/src/auth/models/domain/kdf-config.ts b/libs/common/src/auth/models/domain/kdf-config.ts index ce01f09702..7378081550 100644 --- a/libs/common/src/auth/models/domain/kdf-config.ts +++ b/libs/common/src/auth/models/domain/kdf-config.ts @@ -1,12 +1,7 @@ import { Jsonify } from "type-fest"; -import { - ARGON2_ITERATIONS, - ARGON2_MEMORY, - ARGON2_PARALLELISM, - KdfType, - PBKDF2_ITERATIONS, -} from "../../../platform/enums/kdf-type.enum"; +import { KdfType } from "../../../platform/enums/kdf-type.enum"; +import { RangeWithDefault } from "../../../platform/misc/range-with-default"; /** * Represents a type safe KDF configuration. @@ -17,11 +12,12 @@ export type KdfConfig = PBKDF2KdfConfig | Argon2KdfConfig; * Password-Based Key Derivation Function 2 (PBKDF2) KDF configuration. */ export class PBKDF2KdfConfig { + static ITERATIONS = new RangeWithDefault(600_000, 2_000_000, 600_000); kdfType: KdfType.PBKDF2_SHA256 = KdfType.PBKDF2_SHA256; iterations: number; constructor(iterations?: number) { - this.iterations = iterations ?? PBKDF2_ITERATIONS.defaultValue; + this.iterations = iterations ?? PBKDF2KdfConfig.ITERATIONS.defaultValue; } /** @@ -29,9 +25,9 @@ export class PBKDF2KdfConfig { * A Valid PBKDF2 KDF configuration has KDF iterations between the 600_000 and 2_000_000. */ validateKdfConfig(): void { - if (!PBKDF2_ITERATIONS.inRange(this.iterations)) { + if (!PBKDF2KdfConfig.ITERATIONS.inRange(this.iterations)) { throw new Error( - `PBKDF2 iterations must be between ${PBKDF2_ITERATIONS.min} and ${PBKDF2_ITERATIONS.max}`, + `PBKDF2 iterations must be between ${PBKDF2KdfConfig.ITERATIONS.min} and ${PBKDF2KdfConfig.ITERATIONS.max}`, ); } } @@ -45,15 +41,18 @@ export class PBKDF2KdfConfig { * Argon2 KDF configuration. */ export class Argon2KdfConfig { + static MEMORY = new RangeWithDefault(16, 1024, 64); + static PARALLELISM = new RangeWithDefault(1, 16, 4); + static ITERATIONS = new RangeWithDefault(2, 10, 3); kdfType: KdfType.Argon2id = KdfType.Argon2id; iterations: number; memory: number; parallelism: number; constructor(iterations?: number, memory?: number, parallelism?: number) { - this.iterations = iterations ?? ARGON2_ITERATIONS.defaultValue; - this.memory = memory ?? ARGON2_MEMORY.defaultValue; - this.parallelism = parallelism ?? ARGON2_PARALLELISM.defaultValue; + this.iterations = iterations ?? Argon2KdfConfig.ITERATIONS.defaultValue; + this.memory = memory ?? Argon2KdfConfig.MEMORY.defaultValue; + this.parallelism = parallelism ?? Argon2KdfConfig.PARALLELISM.defaultValue; } /** @@ -61,21 +60,21 @@ export class Argon2KdfConfig { * A Valid Argon2 KDF configuration has iterations between 2 and 10, memory between 16mb and 1024mb, and parallelism between 1 and 16. */ validateKdfConfig(): void { - if (!ARGON2_ITERATIONS.inRange(this.iterations)) { + if (!Argon2KdfConfig.ITERATIONS.inRange(this.iterations)) { throw new Error( - `Argon2 iterations must be between ${ARGON2_ITERATIONS.min} and ${ARGON2_ITERATIONS.max}`, + `Argon2 iterations must be between ${Argon2KdfConfig.ITERATIONS.min} and ${Argon2KdfConfig.ITERATIONS.max}`, ); } - if (!ARGON2_MEMORY.inRange(this.memory)) { + if (!Argon2KdfConfig.MEMORY.inRange(this.memory)) { throw new Error( - `Argon2 memory must be between ${ARGON2_MEMORY.min}mb and ${ARGON2_MEMORY.max}mb`, + `Argon2 memory must be between ${Argon2KdfConfig.MEMORY.min}mb and ${Argon2KdfConfig.MEMORY.max}mb`, ); } - if (!ARGON2_PARALLELISM.inRange(this.parallelism)) { + if (!Argon2KdfConfig.PARALLELISM.inRange(this.parallelism)) { throw new Error( - `Argon2 parallelism must be between ${ARGON2_PARALLELISM.min} and ${ARGON2_PARALLELISM.max}.`, + `Argon2 parallelism must be between ${Argon2KdfConfig.PARALLELISM.min} and ${Argon2KdfConfig.PARALLELISM.max}.`, ); } } @@ -84,3 +83,5 @@ export class Argon2KdfConfig { return new Argon2KdfConfig(json.iterations, json.memory, json.parallelism); } } + +export const DEFAULT_KDF_CONFIG = new PBKDF2KdfConfig(PBKDF2KdfConfig.ITERATIONS.defaultValue); diff --git a/libs/common/src/auth/services/kdf-config.service.spec.ts b/libs/common/src/auth/services/kdf-config.service.spec.ts index 67bcf721bc..7f8357ffb5 100644 --- a/libs/common/src/auth/services/kdf-config.service.spec.ts +++ b/libs/common/src/auth/services/kdf-config.service.spec.ts @@ -1,10 +1,4 @@ import { FakeAccountService, FakeStateProvider, mockAccountServiceWith } from "../../../spec"; -import { - ARGON2_ITERATIONS, - ARGON2_MEMORY, - ARGON2_PARALLELISM, - PBKDF2_ITERATIONS, -} from "../../platform/enums/kdf-type.enum"; import { Utils } from "../../platform/misc/utils"; import { UserId } from "../../types/guid"; import { Argon2KdfConfig, PBKDF2KdfConfig } from "../models/domain/kdf-config"; @@ -77,28 +71,28 @@ describe("KdfConfigService", () => { it("validateKdfConfig(): should throw an error for invalid PBKDF2 iterations", () => { const kdfConfig: PBKDF2KdfConfig = new PBKDF2KdfConfig(100); expect(() => kdfConfig.validateKdfConfig()).toThrow( - `PBKDF2 iterations must be between ${PBKDF2_ITERATIONS.min} and ${PBKDF2_ITERATIONS.max}`, + `PBKDF2 iterations must be between ${PBKDF2KdfConfig.ITERATIONS.min} and ${PBKDF2KdfConfig.ITERATIONS.max}`, ); }); it("validateKdfConfig(): should throw an error for invalid Argon2 iterations", () => { const kdfConfig: Argon2KdfConfig = new Argon2KdfConfig(11, 64, 4); expect(() => kdfConfig.validateKdfConfig()).toThrow( - `Argon2 iterations must be between ${ARGON2_ITERATIONS.min} and ${ARGON2_ITERATIONS.max}`, + `Argon2 iterations must be between ${Argon2KdfConfig.ITERATIONS.min} and ${Argon2KdfConfig.ITERATIONS.max}`, ); }); it("validateKdfConfig(): should throw an error for invalid Argon2 memory", () => { const kdfConfig: Argon2KdfConfig = new Argon2KdfConfig(3, 1025, 4); expect(() => kdfConfig.validateKdfConfig()).toThrow( - `Argon2 memory must be between ${ARGON2_MEMORY.min}mb and ${ARGON2_MEMORY.max}mb`, + `Argon2 memory must be between ${Argon2KdfConfig.MEMORY.min}mb and ${Argon2KdfConfig.MEMORY.max}mb`, ); }); it("validateKdfConfig(): should throw an error for invalid Argon2 parallelism", () => { const kdfConfig: Argon2KdfConfig = new Argon2KdfConfig(3, 64, 17); expect(() => kdfConfig.validateKdfConfig()).toThrow( - `Argon2 parallelism must be between ${ARGON2_PARALLELISM.min} and ${ARGON2_PARALLELISM.max}`, + `Argon2 parallelism must be between ${Argon2KdfConfig.PARALLELISM.min} and ${Argon2KdfConfig.PARALLELISM.max}`, ); }); }); diff --git a/libs/common/src/platform/enums/kdf-type.enum.ts b/libs/common/src/platform/enums/kdf-type.enum.ts index fd29bf308c..29fcd9f1f8 100644 --- a/libs/common/src/platform/enums/kdf-type.enum.ts +++ b/libs/common/src/platform/enums/kdf-type.enum.ts @@ -1,15 +1,4 @@ -import { PBKDF2KdfConfig } from "../../auth/models/domain/kdf-config"; -import { RangeWithDefault } from "../misc/range-with-default"; - export enum KdfType { PBKDF2_SHA256 = 0, Argon2id = 1, } - -export const ARGON2_MEMORY = new RangeWithDefault(16, 1024, 64); -export const ARGON2_PARALLELISM = new RangeWithDefault(1, 16, 4); -export const ARGON2_ITERATIONS = new RangeWithDefault(2, 10, 3); - -export const DEFAULT_KDF_TYPE = KdfType.PBKDF2_SHA256; -export const PBKDF2_ITERATIONS = new RangeWithDefault(600_000, 2_000_000, 600_000); -export const DEFAULT_KDF_CONFIG = new PBKDF2KdfConfig(PBKDF2_ITERATIONS.defaultValue); diff --git a/libs/common/src/platform/services/key-generation.service.ts b/libs/common/src/platform/services/key-generation.service.ts index 2a25ffde2f..b1c1ddfcf1 100644 --- a/libs/common/src/platform/services/key-generation.service.ts +++ b/libs/common/src/platform/services/key-generation.service.ts @@ -1,14 +1,8 @@ -import { KdfConfig } from "../../auth/models/domain/kdf-config"; +import { Argon2KdfConfig, KdfConfig, PBKDF2KdfConfig } from "../../auth/models/domain/kdf-config"; import { CsprngArray } from "../../types/csprng"; import { CryptoFunctionService } from "../abstractions/crypto-function.service"; import { KeyGenerationService as KeyGenerationServiceAbstraction } from "../abstractions/key-generation.service"; -import { - ARGON2_ITERATIONS, - ARGON2_MEMORY, - ARGON2_PARALLELISM, - KdfType, - PBKDF2_ITERATIONS, -} from "../enums"; +import { KdfType } from "../enums"; import { Utils } from "../misc/utils"; import { SymmetricCryptoKey } from "../models/domain/symmetric-crypto-key"; @@ -51,21 +45,21 @@ export class KeyGenerationService implements KeyGenerationServiceAbstraction { let key: Uint8Array = null; if (kdfConfig.kdfType == null || kdfConfig.kdfType === KdfType.PBKDF2_SHA256) { if (kdfConfig.iterations == null) { - kdfConfig.iterations = PBKDF2_ITERATIONS.defaultValue; + kdfConfig.iterations = PBKDF2KdfConfig.ITERATIONS.defaultValue; } key = await this.cryptoFunctionService.pbkdf2(password, salt, "sha256", kdfConfig.iterations); } else if (kdfConfig.kdfType == KdfType.Argon2id) { if (kdfConfig.iterations == null) { - kdfConfig.iterations = ARGON2_ITERATIONS.defaultValue; + kdfConfig.iterations = Argon2KdfConfig.ITERATIONS.defaultValue; } if (kdfConfig.memory == null) { - kdfConfig.memory = ARGON2_MEMORY.defaultValue; + kdfConfig.memory = Argon2KdfConfig.MEMORY.defaultValue; } if (kdfConfig.parallelism == null) { - kdfConfig.parallelism = ARGON2_PARALLELISM.defaultValue; + kdfConfig.parallelism = Argon2KdfConfig.PARALLELISM.defaultValue; } const saltHash = await this.cryptoFunctionService.hash(salt, "sha256"); diff --git a/libs/tools/export/vault-export/vault-export-core/src/services/individual-vault-export.service.spec.ts b/libs/tools/export/vault-export/vault-export-core/src/services/individual-vault-export.service.spec.ts index 9b5c4d8bf5..44df18116d 100644 --- a/libs/tools/export/vault-export/vault-export-core/src/services/individual-vault-export.service.spec.ts +++ b/libs/tools/export/vault-export/vault-export-core/src/services/individual-vault-export.service.spec.ts @@ -2,10 +2,14 @@ import { mock, MockProxy } from "jest-mock-extended"; import { PinServiceAbstraction } from "@bitwarden/auth/common"; import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service"; +import { + DEFAULT_KDF_CONFIG, + PBKDF2KdfConfig, +} from "@bitwarden/common/auth/models/domain/kdf-config"; import { CipherWithIdExport } from "@bitwarden/common/models/export/cipher-with-ids.export"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; -import { DEFAULT_KDF_CONFIG, KdfType, PBKDF2_ITERATIONS } from "@bitwarden/common/platform/enums"; +import { KdfType } from "@bitwarden/common/platform/enums"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { EncryptedString, EncString } from "@bitwarden/common/platform/models/domain/enc-string"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; @@ -238,7 +242,7 @@ describe("VaultExportService", () => { }); it("specifies kdfIterations", () => { - expect(exportObject.kdfIterations).toEqual(PBKDF2_ITERATIONS.defaultValue); + expect(exportObject.kdfIterations).toEqual(PBKDF2KdfConfig.ITERATIONS.defaultValue); }); it("has kdfType", () => { diff --git a/libs/tools/export/vault-export/vault-export-core/src/services/vault-export.service.spec.ts b/libs/tools/export/vault-export/vault-export-core/src/services/vault-export.service.spec.ts index 9b5c4d8bf5..44df18116d 100644 --- a/libs/tools/export/vault-export/vault-export-core/src/services/vault-export.service.spec.ts +++ b/libs/tools/export/vault-export/vault-export-core/src/services/vault-export.service.spec.ts @@ -2,10 +2,14 @@ import { mock, MockProxy } from "jest-mock-extended"; import { PinServiceAbstraction } from "@bitwarden/auth/common"; import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service"; +import { + DEFAULT_KDF_CONFIG, + PBKDF2KdfConfig, +} from "@bitwarden/common/auth/models/domain/kdf-config"; import { CipherWithIdExport } from "@bitwarden/common/models/export/cipher-with-ids.export"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; -import { DEFAULT_KDF_CONFIG, KdfType, PBKDF2_ITERATIONS } from "@bitwarden/common/platform/enums"; +import { KdfType } from "@bitwarden/common/platform/enums"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { EncryptedString, EncString } from "@bitwarden/common/platform/models/domain/enc-string"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; @@ -238,7 +242,7 @@ describe("VaultExportService", () => { }); it("specifies kdfIterations", () => { - expect(exportObject.kdfIterations).toEqual(PBKDF2_ITERATIONS.defaultValue); + expect(exportObject.kdfIterations).toEqual(PBKDF2KdfConfig.ITERATIONS.defaultValue); }); it("has kdfType", () => {