mirror of
https://github.com/bitwarden/browser
synced 2026-02-10 05:30:01 +00:00
Fix unit conversion bug (#13896)
* Fix unit conversion bug * Fix formatting * Fix build
This commit is contained in:
@@ -36,6 +36,8 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv
|
||||
import { AvatarService as AvatarServiceAbstraction } from "@bitwarden/common/auth/abstractions/avatar.service";
|
||||
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
||||
import { MasterPasswordApiService as MasterPasswordApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
|
||||
import { DefaultOpaqueKeyExchangeService } from "@bitwarden/common/auth/opaque/default-opaque-key-exchange.service";
|
||||
import { OpaqueKeyExchangeApiService } from "@bitwarden/common/auth/opaque/opaque-key-exchange-api.service";
|
||||
import {
|
||||
AccountServiceImplementation,
|
||||
getUserId,
|
||||
@@ -44,6 +46,7 @@ import { AuthService } from "@bitwarden/common/auth/services/auth.service";
|
||||
import { AvatarService } from "@bitwarden/common/auth/services/avatar.service";
|
||||
import { DevicesApiServiceImplementation } from "@bitwarden/common/auth/services/devices-api.service.implementation";
|
||||
import { MasterPasswordApiService } from "@bitwarden/common/auth/services/master-password/master-password-api.service.implementation";
|
||||
import { PrePasswordLoginApiService } from "@bitwarden/common/auth/services/pre-password-login-api.service";
|
||||
import { TokenService } from "@bitwarden/common/auth/services/token.service";
|
||||
import { TwoFactorService } from "@bitwarden/common/auth/services/two-factor.service";
|
||||
import { UserVerificationApiService } from "@bitwarden/common/auth/services/user-verification/user-verification-api.service";
|
||||
@@ -640,6 +643,19 @@ export class ServiceContainer {
|
||||
this.configService,
|
||||
);
|
||||
|
||||
const opaqueKeyExchangeApiService = new OpaqueKeyExchangeApiService(
|
||||
this.apiService,
|
||||
this.environmentService,
|
||||
);
|
||||
const opaqueKeyExchangeService = new DefaultOpaqueKeyExchangeService(
|
||||
opaqueKeyExchangeApiService,
|
||||
this.sdkService,
|
||||
);
|
||||
const prePasswordLoginApiService = new PrePasswordLoginApiService(
|
||||
this.apiService,
|
||||
this.environmentService,
|
||||
);
|
||||
|
||||
this.loginStrategyService = new LoginStrategyService(
|
||||
this.accountService,
|
||||
this.masterPasswordService,
|
||||
@@ -666,6 +682,9 @@ export class ServiceContainer {
|
||||
this.vaultTimeoutSettingsService,
|
||||
this.kdfConfigService,
|
||||
this.taskSchedulerService,
|
||||
prePasswordLoginApiService,
|
||||
this.configService,
|
||||
opaqueKeyExchangeService,
|
||||
);
|
||||
|
||||
// FIXME: CLI does not support autofill
|
||||
|
||||
@@ -11,6 +11,7 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv
|
||||
import { MasterPasswordApiService } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { PasswordRequest } from "@bitwarden/common/auth/models/request/password.request";
|
||||
import { CipherConfiguration } from "@bitwarden/common/auth/opaque/models/cipher-configuration";
|
||||
import { OpaqueKeyExchangeService } from "@bitwarden/common/auth/opaque/opaque-key-exchange.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
||||
@@ -24,7 +25,12 @@ import { MasterKey, UserKey } from "@bitwarden/common/types/key";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
import { Argon2KdfConfig, KdfConfigService, KdfType, KeyService } from "@bitwarden/key-management";
|
||||
import {
|
||||
DEFAULT_OPAQUE_KDF_CONFIG,
|
||||
KdfConfigService,
|
||||
KdfType,
|
||||
KeyService,
|
||||
} from "@bitwarden/key-management";
|
||||
|
||||
import { UserKeyRotationService } from "../../key-management/key-rotation/user-key-rotation.service";
|
||||
|
||||
@@ -222,28 +228,22 @@ export class ChangePasswordComponent
|
||||
return this.updateKey();
|
||||
});
|
||||
} else {
|
||||
// PBKDF2 is not recommended for opaque, so force use of Argon2 with default params if the user is using PBKDF2.
|
||||
const userConfiguredKdf = await this.kdfConfigService.getKdfConfig();
|
||||
const opaqueKdf =
|
||||
const cipherConfig = CipherConfiguration.fromKdfConfig(
|
||||
userConfiguredKdf.kdfType === KdfType.Argon2id
|
||||
? userConfiguredKdf
|
||||
: new Argon2KdfConfig();
|
||||
: DEFAULT_OPAQUE_KDF_CONFIG,
|
||||
);
|
||||
|
||||
const sessionId = await this.opaqueKeyExchangeService.register(
|
||||
this.masterPassword,
|
||||
newUserKey[0],
|
||||
opaqueKdf,
|
||||
cipherConfig,
|
||||
);
|
||||
request.opaqueSessionId = sessionId;
|
||||
this.formPromise = this.masterPasswordApiService.postPassword(request);
|
||||
}
|
||||
|
||||
// TODO: remove this test code
|
||||
const userConfiguredKdf = await this.kdfConfigService.getKdfConfig();
|
||||
const opaqueKdf =
|
||||
userConfiguredKdf.kdfType === KdfType.Argon2id ? userConfiguredKdf : new Argon2KdfConfig();
|
||||
await this.opaqueKeyExchangeService.register(this.masterPassword, newUserKey[0], opaqueKdf);
|
||||
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: this.i18nService.t("masterPasswordChanged"),
|
||||
|
||||
@@ -13,6 +13,7 @@ import { IdentityCaptchaResponse } from "@bitwarden/common/auth/models/response/
|
||||
import { IdentityDeviceVerificationResponse } from "@bitwarden/common/auth/models/response/identity-device-verification.response";
|
||||
import { IdentityTokenResponse } from "@bitwarden/common/auth/models/response/identity-token.response";
|
||||
import { IdentityTwoFactorResponse } from "@bitwarden/common/auth/models/response/identity-two-factor.response";
|
||||
import { CipherConfiguration } from "@bitwarden/common/auth/opaque/models/cipher-configuration";
|
||||
import { OpaqueKeyExchangeService } from "@bitwarden/common/auth/opaque/opaque-key-exchange.service";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
@@ -21,7 +22,7 @@ import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/sym
|
||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { MasterKey } from "@bitwarden/common/types/key";
|
||||
import { Argon2KdfConfig, KdfType } from "@bitwarden/key-management";
|
||||
import { DEFAULT_OPAQUE_KDF_CONFIG, KdfType } from "@bitwarden/key-management";
|
||||
|
||||
import { PasswordHashLoginCredentials } from "../models/domain/login-credentials";
|
||||
import { CacheData } from "../services/login-strategies/login-strategy.state";
|
||||
@@ -295,11 +296,14 @@ export class PasswordLoginStrategy extends BaseLoginStrategy {
|
||||
return;
|
||||
}
|
||||
|
||||
const opaqueKdf =
|
||||
userConfiguredKdf.kdfType === KdfType.Argon2id ? userConfiguredKdf : new Argon2KdfConfig();
|
||||
const cipherConfig = CipherConfiguration.fromKdfConfig(
|
||||
userConfiguredKdf.kdfType === KdfType.Argon2id
|
||||
? userConfiguredKdf
|
||||
: DEFAULT_OPAQUE_KDF_CONFIG,
|
||||
);
|
||||
|
||||
try {
|
||||
await this.opaqueKeyExchangeService.register(masterPassword, userKey, opaqueKdf);
|
||||
await this.opaqueKeyExchangeService.register(masterPassword, userKey, cipherConfig);
|
||||
} catch (error) {
|
||||
// If this process fails for any reason, we don't want to stop the login process
|
||||
// so just log the error and continue.
|
||||
|
||||
@@ -11,6 +11,7 @@ import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/ide
|
||||
import { IdentityTokenResponse } from "@bitwarden/common/auth/models/response/identity-token.response";
|
||||
import { IdentityTwoFactorResponse } from "@bitwarden/common/auth/models/response/identity-two-factor.response";
|
||||
import { PrePasswordLoginResponse } from "@bitwarden/common/auth/models/response/pre-password-login.response";
|
||||
import { OpaqueKeyExchangeService } from "@bitwarden/common/auth/opaque/opaque-key-exchange.service";
|
||||
import { PrePasswordLoginApiService } from "@bitwarden/common/auth/services/pre-password-login-api.service";
|
||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
|
||||
@@ -22,6 +23,7 @@ import {
|
||||
VaultTimeoutSettingsService,
|
||||
} from "@bitwarden/common/key-management/vault-timeout";
|
||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
@@ -48,8 +50,6 @@ import { UserDecryptionOptionsService } from "../user-decryption-options/user-de
|
||||
|
||||
import { LoginStrategyService } from "./login-strategy.service";
|
||||
import { CACHE_EXPIRATION_KEY } from "./login-strategy.state";
|
||||
import { OpaqueKeyExchangeService } from "@bitwarden/common/auth/opaque/opaque-key-exchange.service";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
|
||||
// TODO: update tests to pass
|
||||
// TODO: test makePrePasswordLoginMasterKey
|
||||
|
||||
@@ -8,7 +8,7 @@ import { OpaqueSessionId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import { UserKey } from "../../types/key";
|
||||
|
||||
import { Argon2IdParameters, CipherConfiguration } from "./models/cipher-configuration";
|
||||
import { CipherConfiguration } from "./models/cipher-configuration";
|
||||
import { LoginFinishRequest } from "./models/login-finish.request";
|
||||
import { LoginStartRequest } from "./models/login-start.request";
|
||||
import { RegistrationFinishRequest } from "./models/registration-finish.request";
|
||||
@@ -25,15 +25,14 @@ export class DefaultOpaqueKeyExchangeService implements OpaqueKeyExchangeService
|
||||
async register(
|
||||
masterPassword: string,
|
||||
userKey: UserKey,
|
||||
keyStretchingFuncArgon2Params: Argon2IdParameters, // TODO: eval if we can use KdfConfig existing type
|
||||
cipherConfig: CipherConfiguration,
|
||||
): Promise<OpaqueSessionId> {
|
||||
if (!masterPassword || !userKey || !keyStretchingFuncArgon2Params) {
|
||||
if (!masterPassword || !userKey || !cipherConfig) {
|
||||
throw new Error(
|
||||
`Unable to register user with missing parameters. masterPassword exists: ${!!masterPassword}, userKey exists: ${!!userKey}, keyStretchingFuncArgon2Params exists: ${!!keyStretchingFuncArgon2Params}`,
|
||||
`Unable to register user with missing parameters. masterPassword exists: ${!!masterPassword}, userKey exists: ${!!userKey}, cipherConfig exists: ${!!cipherConfig}`,
|
||||
);
|
||||
}
|
||||
|
||||
const cipherConfig = new CipherConfiguration(keyStretchingFuncArgon2Params);
|
||||
const cryptoClient = (await firstValueFrom(this.sdkService.client$)).crypto();
|
||||
|
||||
const registrationStart = cryptoClient.opaque_register_start(
|
||||
@@ -81,15 +80,14 @@ export class DefaultOpaqueKeyExchangeService implements OpaqueKeyExchangeService
|
||||
async login(
|
||||
email: string,
|
||||
masterPassword: string,
|
||||
keyStretchingFuncArgon2Params: Argon2IdParameters,
|
||||
cipherConfig: CipherConfiguration,
|
||||
): Promise<Uint8Array> {
|
||||
if (!email || !masterPassword || !keyStretchingFuncArgon2Params) {
|
||||
if (!email || !masterPassword || !cipherConfig) {
|
||||
throw new Error(
|
||||
`Unable to log in user with missing parameters. email exists: ${!!email}; masterPassword exists: ${!!masterPassword}; keyStretchingFuncArgon2Params exists: ${!!keyStretchingFuncArgon2Params}`,
|
||||
`Unable to log in user with missing parameters. email exists: ${!!email}; masterPassword exists: ${!!masterPassword}; cipherConfig exists: ${!!cipherConfig}`,
|
||||
);
|
||||
}
|
||||
|
||||
const cipherConfig = new CipherConfiguration(keyStretchingFuncArgon2Params);
|
||||
const cryptoClient = (await firstValueFrom(this.sdkService.client$)).crypto();
|
||||
|
||||
const loginStart = cryptoClient.opaque_login_start(masterPassword, cipherConfig.toSdkConfig());
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Argon2KdfConfig } from "@bitwarden/key-management";
|
||||
import { CipherConfiguration as CipherConfigurationSdk } from "@bitwarden/sdk-internal";
|
||||
|
||||
// TODO: add js docs to all types / classes here.
|
||||
@@ -16,6 +17,21 @@ export class CipherConfiguration {
|
||||
this.argon2Parameters = ksf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts from Bitwarden KDF configs to OPAQUE KSF configs.
|
||||
*
|
||||
* @param kdfConfig - Bitwarden KDF config
|
||||
* @returns OPAQUE KSF config
|
||||
*/
|
||||
static fromKdfConfig(kdfConfig: Argon2KdfConfig): CipherConfiguration {
|
||||
return new CipherConfiguration({
|
||||
// convert MiB to KiB
|
||||
memory: kdfConfig.memory * 1024,
|
||||
iterations: kdfConfig.iterations,
|
||||
parallelism: kdfConfig.parallelism,
|
||||
});
|
||||
}
|
||||
|
||||
toSdkConfig(): CipherConfigurationSdk {
|
||||
if (
|
||||
this.cipherSuite !== "OPAQUE_3_RISTRETTO255_OPRF_RISTRETTO255_KEGROUP_3DH_KEX_ARGON2ID13_KSF"
|
||||
|
||||
@@ -2,7 +2,7 @@ import { OpaqueSessionId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import { UserKey } from "../../types/key";
|
||||
|
||||
import { Argon2IdParameters } from "./models/cipher-configuration";
|
||||
import { CipherConfiguration } from "./models/cipher-configuration";
|
||||
|
||||
export abstract class OpaqueKeyExchangeService {
|
||||
/**
|
||||
@@ -11,7 +11,7 @@ export abstract class OpaqueKeyExchangeService {
|
||||
abstract register(
|
||||
masterPassword: string,
|
||||
userKey: UserKey,
|
||||
ksfParameters: Argon2IdParameters,
|
||||
cipherConfiguration: CipherConfiguration,
|
||||
): Promise<OpaqueSessionId>;
|
||||
|
||||
/**
|
||||
@@ -22,6 +22,6 @@ export abstract class OpaqueKeyExchangeService {
|
||||
abstract login(
|
||||
email: string,
|
||||
masterPassword: string,
|
||||
ksfParameters: Argon2IdParameters,
|
||||
cipherConfiguration: CipherConfiguration,
|
||||
): Promise<Uint8Array>;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ export {
|
||||
KdfConfig,
|
||||
createKdfConfig,
|
||||
DEFAULT_KDF_CONFIG,
|
||||
DEFAULT_OPAQUE_KDF_CONFIG,
|
||||
} from "./models/kdf-config";
|
||||
export { KdfConfigService } from "./abstractions/kdf-config.service";
|
||||
export { DefaultKdfConfigService } from "./kdf-config.service";
|
||||
|
||||
@@ -141,3 +141,4 @@ export class Argon2KdfConfig {
|
||||
}
|
||||
|
||||
export const DEFAULT_KDF_CONFIG = new PBKDF2KdfConfig(PBKDF2KdfConfig.ITERATIONS.defaultValue);
|
||||
export const DEFAULT_OPAQUE_KDF_CONFIG = new Argon2KdfConfig(1, 256, 1);
|
||||
|
||||
Reference in New Issue
Block a user