diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 57812aa82..cef8a7a2c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -71,6 +71,11 @@ jobs: with: nuget-version: 5.9.0 + - name: Set up .NET + uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3.2.0 + with: + dotnet-version: '3.1.x' + - name: Set up MSBuild uses: microsoft/setup-msbuild@1ff57057b5cfdc39105cd07a01d78e9b0ea0c14c # v1.3.1 diff --git a/.github/workflows/version-auto-bump.yml b/.github/workflows/version-auto-bump.yml index 5e2d17fb9..c486d1535 100644 --- a/.github/workflows/version-auto-bump.yml +++ b/.github/workflows/version-auto-bump.yml @@ -32,14 +32,10 @@ jobs: echo "new-version=$NEW_VER" >> $GITHUB_OUTPUT trigger_version_bump: - name: "Version bump" - runs-on: ubuntu-22.04 - needs: - - setup - steps: - - name: Bump version to ${{ needs.setup.outputs.version_number }} - uses: ./.github/workflows/version-bump.yml - secrets: - AZURE_PROD_KV_CREDENTIALS: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} - with: - version_number: ${{ needs.setup.outputs.version_number }} + name: Bump version to ${{ needs.setup.outputs.version_number }} + needs: setup + uses: ./.github/workflows/version-bump.yml + secrets: + AZURE_PROD_KV_CREDENTIALS: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} + with: + version_number: ${{ needs.setup.outputs.version_number }} diff --git a/crowdin.yml b/crowdin.yml index 57dfe8ff7..45e3e516d 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -38,3 +38,15 @@ files: pt-PT: pt-PT en-GB: en-GB en-IN: en-IN + - source: "/src/watchOS/bitwarden/bitwarden WatchKit Extension/Localization/en.lproj/Localizable.strings" + dest: "/src/watchOS/bitwarden/bitwarden WatchKit Extension/Localization/en.lproj/%original_file_name%" + translation: "/src/watchOS/bitwarden/bitwarden WatchKit Extension/Localization//%two_letters_code%.lproj/%original_file_name%" + update_option: update_as_unapproved + languages_mapping: + two_letters_code: + zh-CN: zh-Hans + zh-TW: zh-Hant + pt-BR: pt-BR + pt-PT: pt-PT + en-GB: en-GB + en-IN: en-IN diff --git a/src/Android/Android.csproj b/src/Android/Android.csproj index c5f838ff8..8561fb4f1 100644 --- a/src/Android/Android.csproj +++ b/src/Android/Android.csproj @@ -233,6 +233,18 @@ + + + + + + + + + + + + diff --git a/src/Android/Properties/AndroidManifest.xml b/src/Android/Properties/AndroidManifest.xml index 77372ff73..b4658aa9d 100644 --- a/src/Android/Properties/AndroidManifest.xml +++ b/src/Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + diff --git a/src/Android/Renderers/CustomLabelRenderer.cs b/src/Android/Renderers/CustomLabelRenderer.cs index 62287087d..838b9b967 100644 --- a/src/Android/Renderers/CustomLabelRenderer.cs +++ b/src/Android/Renderers/CustomLabelRenderer.cs @@ -1,10 +1,10 @@ -using System; -using Bit.App.Controls; -using System.ComponentModel; -using Xamarin.Forms.Platform.Android; +using System.ComponentModel; using Android.Content; -using Xamarin.Forms; +using Android.OS; +using Bit.App.Controls; using Bit.Droid.Renderers; +using Xamarin.Forms; +using Xamarin.Forms.Platform.Android; [assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRenderer))] namespace Bit.Droid.Renderers @@ -15,6 +15,19 @@ namespace Bit.Droid.Renderers : base(context) { } + protected override void OnElementChanged(ElementChangedEventArgs @@ -442,5 +443,6 @@ + diff --git a/src/App/Controls/CustomLabel.cs b/src/App/Controls/CustomLabel.cs index e822d3304..77d1fda79 100644 --- a/src/App/Controls/CustomLabel.cs +++ b/src/App/Controls/CustomLabel.cs @@ -1,5 +1,4 @@ -using System; -using Xamarin.Forms; +using Xamarin.Forms; namespace Bit.App.Controls { @@ -8,6 +7,7 @@ namespace Bit.App.Controls public CustomLabel() { } + + public int? FontWeight { get; set; } } } - diff --git a/src/App/Pages/Accounts/LockPage.xaml b/src/App/Pages/Accounts/LockPage.xaml index f34a8b284..dabcb9fd6 100644 --- a/src/App/Pages/Accounts/LockPage.xaml +++ b/src/App/Pages/Accounts/LockPage.xaml @@ -46,7 +46,7 @@ @@ -89,7 +89,7 @@ diff --git a/src/App/Pages/Accounts/LockPage.xaml.cs b/src/App/Pages/Accounts/LockPage.xaml.cs index f5a7914a5..d62b4c6b2 100644 --- a/src/App/Pages/Accounts/LockPage.xaml.cs +++ b/src/App/Pages/Accounts/LockPage.xaml.cs @@ -44,7 +44,7 @@ namespace Bit.App.Pages { get { - if (_vm?.PinLock ?? false) + if (_vm?.PinEnabled ?? false) { return _pin; } @@ -54,7 +54,7 @@ namespace Bit.App.Pages public async Task PromptBiometricAfterResumeAsync() { - if (_vm.BiometricLock) + if (_vm.BiometricEnabled) { await Task.Delay(500); if (!_promptedAfterResume) @@ -91,13 +91,13 @@ namespace Bit.App.Pages _vm.FocusSecretEntry += PerformFocusSecretEntry; - if (!_vm.BiometricLock) + if (!_vm.BiometricEnabled) { RequestFocus(SecretEntry); } else { - if (_vm.UsingKeyConnector && !_vm.PinLock) + if (_vm.UsingKeyConnector && !_vm.PinEnabled) { _passwordGrid.IsVisible = false; _unlockButton.IsVisible = false; diff --git a/src/App/Pages/Accounts/LockPageViewModel.cs b/src/App/Pages/Accounts/LockPageViewModel.cs index 26d15c630..dc6221e2e 100644 --- a/src/App/Pages/Accounts/LockPageViewModel.cs +++ b/src/App/Pages/Accounts/LockPageViewModel.cs @@ -38,16 +38,15 @@ namespace Bit.App.Pages private string _masterPassword; private string _pin; private bool _showPassword; - private bool _pinLock; - private bool _biometricLock; + private PinLockEnum _pinStatus; + private bool _pinEnabled; + private bool _biometricEnabled; private bool _biometricIntegrityValid = true; private bool _biometricButtonVisible; private bool _usingKeyConnector; private string _biometricButtonText; private string _loggedInAsText; private string _lockedVerifyText; - private bool _isPinProtected; - private bool _isPinProtectedWithKey; public LockPageViewModel() { @@ -101,10 +100,10 @@ namespace Bit.App.Pages }); } - public bool PinLock + public bool PinEnabled { - get => _pinLock; - set => SetProperty(ref _pinLock, value); + get => _pinEnabled; + set => SetProperty(ref _pinEnabled, value); } public bool UsingKeyConnector @@ -112,10 +111,10 @@ namespace Bit.App.Pages get => _usingKeyConnector; } - public bool BiometricLock + public bool BiometricEnabled { - get => _biometricLock; - set => SetProperty(ref _biometricLock, value); + get => _biometricEnabled; + set => SetProperty(ref _biometricEnabled, value); } public bool BiometricIntegrityValid @@ -163,14 +162,18 @@ namespace Bit.App.Pages public async Task InitAsync() { - (_isPinProtected, _isPinProtectedWithKey) = await _vaultTimeoutService.IsPinLockSetAsync(); - PinLock = (_isPinProtected && await _stateService.GetPinProtectedKeyAsync() != null) || - _isPinProtectedWithKey; - BiometricLock = await _vaultTimeoutService.IsBiometricLockSetAsync() && await _cryptoService.HasKeyAsync(); + _pinStatus = await _vaultTimeoutService.IsPinLockSetAsync(); + + var ephemeralPinSet = await _stateService.GetUserKeyPinEphemeralAsync() + ?? await _stateService.GetPinProtectedKeyAsync(); + PinEnabled = (_pinStatus == PinLockEnum.Transient && ephemeralPinSet != null) || + _pinStatus == PinLockEnum.Persistent; + + BiometricEnabled = await _vaultTimeoutService.IsBiometricLockSetAsync() && await _cryptoService.HasEncryptedUserKeyAsync(); // Users with key connector and without biometric or pin has no MP to unlock with _usingKeyConnector = await _keyConnectorService.GetUsesKeyConnector(); - if (_usingKeyConnector && !(BiometricLock || PinLock)) + if (_usingKeyConnector && !(BiometricEnabled || PinEnabled)) { await _vaultTimeoutService.LogOutAsync(); return; @@ -189,7 +192,7 @@ namespace Bit.App.Pages } var webVaultHostname = CoreHelpers.GetHostname(webVault); LoggedInAsText = string.Format(AppResources.LoggedInAsOn, _email, webVaultHostname); - if (PinLock) + if (PinEnabled) { PageTitle = AppResources.VerifyPIN; LockedVerifyText = AppResources.VaultLockedPIN; @@ -208,7 +211,7 @@ namespace Bit.App.Pages } } - if (BiometricLock) + if (BiometricEnabled) { BiometricIntegrityValid = await _platformUtilsService.IsBiometricIntegrityValidAsync(); if (!_biometricIntegrityValid) @@ -230,14 +233,14 @@ namespace Bit.App.Pages public async Task SubmitAsync() { - if (PinLock && string.IsNullOrWhiteSpace(Pin)) + if (PinEnabled && string.IsNullOrWhiteSpace(Pin)) { await Page.DisplayAlert(AppResources.AnErrorHasOccurred, string.Format(AppResources.ValidationFieldRequired, AppResources.PIN), AppResources.Ok); return; } - if (!PinLock && string.IsNullOrWhiteSpace(MasterPassword)) + if (!PinEnabled && string.IsNullOrWhiteSpace(MasterPassword)) { await Page.DisplayAlert(AppResources.AnErrorHasOccurred, string.Format(AppResources.ValidationFieldRequired, AppResources.MasterPassword), @@ -248,34 +251,54 @@ namespace Bit.App.Pages ShowPassword = false; var kdfConfig = await _stateService.GetActiveUserCustomDataAsync(a => new KdfConfig(a?.Profile)); - if (PinLock) + if (PinEnabled) { var failed = true; try { - if (_isPinProtected) + EncString userKeyPin = null; + EncString oldPinProtected = null; + if (_pinStatus == PinLockEnum.Persistent) { - var key = await _cryptoService.MakeKeyFromPinAsync(Pin, _email, + userKeyPin = await _stateService.GetUserKeyPinAsync(); + var oldEncryptedKey = await _stateService.GetPinProtectedAsync(); + oldPinProtected = oldEncryptedKey != null ? new EncString(oldEncryptedKey) : null; + } + else if (_pinStatus == PinLockEnum.Transient) + { + userKeyPin = await _stateService.GetUserKeyPinEphemeralAsync(); + oldPinProtected = await _stateService.GetPinProtectedKeyAsync(); + } + + UserKey userKey; + if (oldPinProtected != null) + { + userKey = await _cryptoService.DecryptAndMigrateOldPinKeyAsync( + _pinStatus == PinLockEnum.Transient, + Pin, + _email, kdfConfig, - await _stateService.GetPinProtectedKeyAsync()); - var encKey = await _cryptoService.GetEncKeyAsync(key); - var protectedPin = await _stateService.GetProtectedPinAsync(); - var decPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), encKey); - failed = decPin != Pin; - if (!failed) - { - Pin = string.Empty; - await AppHelpers.ResetInvalidUnlockAttemptsAsync(); - await SetKeyAndContinueAsync(key); - } + oldPinProtected + ); } else { - var key = await _cryptoService.MakeKeyFromPinAsync(Pin, _email, kdfConfig); - failed = false; + userKey = await _cryptoService.DecryptUserKeyWithPinAsync( + Pin, + _email, + kdfConfig, + userKeyPin + ); + } + + var protectedPin = await _stateService.GetProtectedPinAsync(); + var decryptedPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), userKey); + failed = decryptedPin != Pin; + if (!failed) + { Pin = string.Empty; await AppHelpers.ResetInvalidUnlockAttemptsAsync(); - await SetKeyAndContinueAsync(key); + await SetKeyAndContinueAsync(userKey); } } catch @@ -296,19 +319,21 @@ namespace Bit.App.Pages } else { - var key = await _cryptoService.MakeKeyAsync(MasterPassword, _email, kdfConfig); - var storedKeyHash = await _cryptoService.GetKeyHashAsync(); + var masterKey = await _cryptoService.MakeMasterKeyAsync(MasterPassword, _email, kdfConfig); + var storedKeyHash = await _cryptoService.GetPasswordHashAsync(); var passwordValid = false; MasterPasswordPolicyOptions enforcedMasterPasswordOptions = null; if (storedKeyHash != null) { - passwordValid = await _cryptoService.CompareAndUpdateKeyHashAsync(MasterPassword, key); + // Offline unlock possible + passwordValid = await _cryptoService.CompareAndUpdatePasswordHashAsync(MasterPassword, masterKey); } else { + // Online unlock required await _deviceActionService.ShowLoadingAsync(AppResources.Loading); - var keyHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.ServerAuthorization); + var keyHash = await _cryptoService.HashPasswordAsync(MasterPassword, masterKey, HashPurpose.ServerAuthorization); var request = new PasswordVerificationRequest(); request.MasterPasswordHash = keyHash; @@ -317,8 +342,8 @@ namespace Bit.App.Pages var response = await _apiService.PostAccountVerifyPasswordAsync(request); enforcedMasterPasswordOptions = response.MasterPasswordPolicy; passwordValid = true; - var localKeyHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.LocalAuthorization); - await _cryptoService.SetKeyHashAsync(localKeyHash); + var localKeyHash = await _cryptoService.HashPasswordAsync(MasterPassword, masterKey, HashPurpose.LocalAuthorization); + await _cryptoService.SetPasswordHashAsync(localKeyHash); } catch (Exception e) { @@ -328,15 +353,6 @@ namespace Bit.App.Pages } if (passwordValid) { - if (_isPinProtected) - { - var protectedPin = await _stateService.GetProtectedPinAsync(); - var encKey = await _cryptoService.GetEncKeyAsync(key); - var decPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), encKey); - var pinKey = await _cryptoService.MakePinKeyAysnc(decPin, _email, kdfConfig); - await _stateService.SetPinProtectedKeyAsync(await _cryptoService.EncryptAsync(key.Key, pinKey)); - } - if (await RequirePasswordChangeAsync(enforcedMasterPasswordOptions)) { // Save the ForcePasswordResetReason to force a password reset after unlock @@ -346,10 +362,13 @@ namespace Bit.App.Pages MasterPassword = string.Empty; await AppHelpers.ResetInvalidUnlockAttemptsAsync(); - await SetKeyAndContinueAsync(key); + + var userKey = await _cryptoService.DecryptUserKeyWithMasterKeyAsync(masterKey); + await _cryptoService.SetMasterKeyAsync(masterKey); + await SetKeyAndContinueAsync(userKey); // Re-enable biometrics - if (BiometricLock & !BiometricIntegrityValid) + if (BiometricEnabled & !BiometricIntegrityValid) { await _biometricService.SetupBiometricAsync(); } @@ -426,7 +445,7 @@ namespace Bit.App.Pages public void TogglePassword() { ShowPassword = !ShowPassword; - var secret = PinLock ? Pin : MasterPassword; + var secret = PinEnabled ? Pin : MasterPassword; _secretEntryFocusWeakEventManager.RaiseEvent(string.IsNullOrEmpty(secret) ? 0 : secret.Length, nameof(FocusSecretEntry)); } @@ -434,12 +453,12 @@ namespace Bit.App.Pages { BiometricIntegrityValid = await _platformUtilsService.IsBiometricIntegrityValidAsync(); BiometricButtonVisible = BiometricIntegrityValid; - if (!BiometricLock || !BiometricIntegrityValid) + if (!BiometricEnabled || !BiometricIntegrityValid) { return; } var success = await _platformUtilsService.AuthenticateBiometricAsync(null, - PinLock ? AppResources.PIN : AppResources.MasterPassword, + PinEnabled ? AppResources.PIN : AppResources.MasterPassword, () => _secretEntryFocusWeakEventManager.RaiseEvent((int?)null, nameof(FocusSecretEntry))); await _stateService.SetBiometricLockedAsync(!success); if (success) @@ -448,12 +467,12 @@ namespace Bit.App.Pages } } - private async Task SetKeyAndContinueAsync(SymmetricCryptoKey key) + private async Task SetKeyAndContinueAsync(UserKey key) { - var hasKey = await _cryptoService.HasKeyAsync(); + var hasKey = await _cryptoService.HasUserKeyAsync(); if (!hasKey) { - await _cryptoService.SetKeyAsync(key); + await _cryptoService.SetUserKeyAsync(key); } await _deviceTrustCryptoService.TrustDeviceIfNeededAsync(); await DoContinueAsync(); diff --git a/src/App/Pages/Accounts/RegisterPageViewModel.cs b/src/App/Pages/Accounts/RegisterPageViewModel.cs index ebfc522c1..b742a65ba 100644 --- a/src/App/Pages/Accounts/RegisterPageViewModel.cs +++ b/src/App/Pages/Accounts/RegisterPageViewModel.cs @@ -177,25 +177,28 @@ namespace Bit.App.Pages Name = string.IsNullOrWhiteSpace(Name) ? null : Name; Email = Email.Trim().ToLower(); var kdfConfig = new KdfConfig(KdfType.PBKDF2_SHA256, Constants.Pbkdf2Iterations, null, null); - var key = await _cryptoService.MakeKeyAsync(MasterPassword, Email, kdfConfig); - var encKey = await _cryptoService.MakeEncKeyAsync(key); - var hashedPassword = await _cryptoService.HashPasswordAsync(MasterPassword, key); - var keys = await _cryptoService.MakeKeyPairAsync(encKey.Item1); + var newMasterKey = await _cryptoService.MakeMasterKeyAsync(MasterPassword, Email, kdfConfig); + var (newUserKey, newProtectedUserKey) = await _cryptoService.EncryptUserKeyWithMasterKeyAsync( + newMasterKey, + await _cryptoService.MakeUserKeyAsync() + ); + var hashedPassword = await _cryptoService.HashPasswordAsync(MasterPassword, newMasterKey); + var (newPublicKey, newProtectedPrivateKey) = await _cryptoService.MakeKeyPairAsync(newUserKey); var request = new RegisterRequest { Email = Email, Name = Name, MasterPasswordHash = hashedPassword, MasterPasswordHint = Hint, - Key = encKey.Item2.EncryptedString, + Key = newProtectedUserKey.EncryptedString, Kdf = kdfConfig.Type, KdfIterations = kdfConfig.Iterations, KdfMemory = kdfConfig.Memory, KdfParallelism = kdfConfig.Parallelism, Keys = new KeysRequest { - PublicKey = keys.Item1, - EncryptedPrivateKey = keys.Item2.EncryptedString + PublicKey = newPublicKey, + EncryptedPrivateKey = newProtectedPrivateKey.EncryptedString }, CaptchaResponse = _captchaToken, }; diff --git a/src/App/Pages/Accounts/SetPasswordPageViewModel.cs b/src/App/Pages/Accounts/SetPasswordPageViewModel.cs index 51d468275..57ffaac79 100644 --- a/src/App/Pages/Accounts/SetPasswordPageViewModel.cs +++ b/src/App/Pages/Accounts/SetPasswordPageViewModel.cs @@ -165,26 +165,18 @@ namespace Bit.App.Pages var kdfConfig = new KdfConfig(KdfType.PBKDF2_SHA256, Constants.Pbkdf2Iterations, null, null); var email = await _stateService.GetEmailAsync(); - var key = await _cryptoService.MakeKeyAsync(MasterPassword, email, kdfConfig); - var masterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.ServerAuthorization); - var localMasterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.LocalAuthorization); + var newMasterKey = await _cryptoService.MakeMasterKeyAsync(MasterPassword, email, kdfConfig); + var masterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, newMasterKey, HashPurpose.ServerAuthorization); + var localMasterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, newMasterKey, HashPurpose.LocalAuthorization); - Tuple encKey; - var existingEncKey = await _cryptoService.GetEncKeyAsync(); - if (existingEncKey == null) - { - encKey = await _cryptoService.MakeEncKeyAsync(key); - } - else - { - encKey = await _cryptoService.RemakeEncKeyAsync(key); - } + var (newUserKey, newProtectedUserKey) = await _cryptoService.EncryptUserKeyWithMasterKeyAsync(newMasterKey, + await _cryptoService.GetUserKeyAsync() ?? await _cryptoService.MakeUserKeyAsync()); - var keys = await _cryptoService.MakeKeyPairAsync(encKey.Item1); + var keys = await _cryptoService.MakeKeyPairAsync(newUserKey); var request = new SetPasswordRequest { MasterPasswordHash = masterPasswordHash, - Key = encKey.Item2.EncryptedString, + Key = newProtectedUserKey.EncryptedString, MasterPasswordHint = Hint, Kdf = kdfConfig.Type.GetValueOrDefault(KdfType.PBKDF2_SHA256), KdfIterations = kdfConfig.Iterations.GetValueOrDefault(Constants.Pbkdf2Iterations), @@ -204,19 +196,19 @@ namespace Bit.App.Pages // Set Password and relevant information await _apiService.SetPasswordAsync(request); await _stateService.SetKdfConfigurationAsync(kdfConfig); - await _cryptoService.SetKeyAsync(key); - await _cryptoService.SetKeyHashAsync(localMasterPasswordHash); - await _cryptoService.SetEncKeyAsync(encKey.Item2.EncryptedString); - await _cryptoService.SetEncPrivateKeyAsync(keys.Item2.EncryptedString); + await _cryptoService.SetMasterKeyAsync(newMasterKey); + await _cryptoService.SetPasswordHashAsync(localMasterPasswordHash); + await _cryptoService.SetMasterKeyEncryptedUserKeyAsync(newProtectedUserKey.EncryptedString); + await _cryptoService.SetPrivateKeyAsync(keys.Item2.EncryptedString); if (ResetPasswordAutoEnroll) { // Grab Organization Keys var response = await _apiService.GetOrganizationKeysAsync(OrgId); var publicKey = CoreHelpers.Base64UrlDecode(response.PublicKey); - // Grab user's Encryption Key and encrypt with Org Public Key - var userEncKey = await _cryptoService.GetEncKeyAsync(); - var encryptedKey = await _cryptoService.RsaEncryptAsync(userEncKey.Key, publicKey); + // Grab User Key and encrypt with Org Public Key + var userKey = await _cryptoService.GetUserKeyAsync(); + var encryptedKey = await _cryptoService.RsaEncryptAsync(userKey.Key, publicKey); // Request var resetRequest = new OrganizationUserResetPasswordEnrollmentRequest { diff --git a/src/App/Pages/Accounts/UpdateTempPasswordPageViewModel.cs b/src/App/Pages/Accounts/UpdateTempPasswordPageViewModel.cs index daf4b2dbe..7d8ec85f0 100644 --- a/src/App/Pages/Accounts/UpdateTempPasswordPageViewModel.cs +++ b/src/App/Pages/Accounts/UpdateTempPasswordPageViewModel.cs @@ -93,12 +93,12 @@ namespace Bit.App.Pages var kdfConfig = await _stateService.GetActiveUserCustomDataAsync(a => new KdfConfig(a?.Profile)); var email = await _stateService.GetEmailAsync(); - // Create new key and hash new password - var key = await _cryptoService.MakeKeyAsync(MasterPassword, email, kdfConfig); - var masterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, key); + // Create new master key and hash new password + var masterKey = await _cryptoService.MakeMasterKeyAsync(MasterPassword, email, kdfConfig); + var masterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, masterKey); - // Create new encKey for the User - var newEncKey = await _cryptoService.RemakeEncKeyAsync(key); + // Encrypt user key with new master key + var (userKey, newProtectedUserKey) = await _cryptoService.EncryptUserKeyWithMasterKeyAsync(masterKey); // Initiate API action try @@ -108,10 +108,10 @@ namespace Bit.App.Pages switch (_reason) { case ForcePasswordResetReason.AdminForcePasswordReset: - await UpdateTempPasswordAsync(masterPasswordHash, newEncKey.Item2.EncryptedString); + await UpdateTempPasswordAsync(masterPasswordHash, newProtectedUserKey.EncryptedString); break; case ForcePasswordResetReason.WeakMasterPasswordOnLogin: - await UpdatePasswordAsync(masterPasswordHash, newEncKey.Item2.EncryptedString); + await UpdatePasswordAsync(masterPasswordHash, newProtectedUserKey.EncryptedString); break; default: throw new ArgumentOutOfRangeException(); diff --git a/src/App/Pages/Settings/BlockAutofillUrisPage.xaml b/src/App/Pages/Settings/BlockAutofillUrisPage.xaml new file mode 100644 index 000000000..8514edcad --- /dev/null +++ b/src/App/Pages/Settings/BlockAutofillUrisPage.xaml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +