diff --git a/src/Core/Exceptions/UserAndMasterKeyNullException.cs b/src/Core/Exceptions/UserAndMasterKeyNullException.cs new file mode 100644 index 000000000..8638208a2 --- /dev/null +++ b/src/Core/Exceptions/UserAndMasterKeyNullException.cs @@ -0,0 +1,12 @@ +using System; +namespace Bit.Core.Exceptions +{ + public class UserAndMasterKeysNullException : Exception + { + public UserAndMasterKeysNullException() + : base("UserKey and MasterKey are null.") + { + } + } +} + diff --git a/src/Core/Models/Request/PasswordlessLoginRequest.cs b/src/Core/Models/Request/PasswordlessLoginRequest.cs index 1ed5a380c..3a1f84d69 100644 --- a/src/Core/Models/Request/PasswordlessLoginRequest.cs +++ b/src/Core/Models/Request/PasswordlessLoginRequest.cs @@ -8,7 +8,7 @@ namespace Bit.Core.Models.Request bool requestApproved) { Key = key ?? throw new ArgumentNullException(nameof(key)); - MasterPasswordHash = masterPasswordHash ?? throw new ArgumentNullException(nameof(masterPasswordHash)); + MasterPasswordHash = masterPasswordHash; DeviceIdentifier = deviceIdentifier ?? throw new ArgumentNullException(nameof(deviceIdentifier)); RequestApproved = requestApproved; } diff --git a/src/Core/Services/AuthService.cs b/src/Core/Services/AuthService.cs index 7b7e8ab57..24f979f0f 100644 --- a/src/Core/Services/AuthService.cs +++ b/src/Core/Services/AuthService.cs @@ -214,7 +214,9 @@ namespace Bit.Core.Services } else { - var userKey = await _cryptoService.DecryptUserKeyWithMasterKeyAsync(new MasterKey(decryptedKey)); + var masterKey = new MasterKey(decryptedKey); + var userKey = await _cryptoService.DecryptUserKeyWithMasterKeyAsync(masterKey); + await _cryptoService.SetMasterKeyAsync(masterKey); await _cryptoService.SetUserKeyAsync(userKey); } await _deviceTrustCryptoService.TrustDeviceIfNeededAsync(); @@ -632,13 +634,29 @@ namespace Bit.Core.Services { var publicKey = CoreHelpers.Base64UrlDecode(pubKey); var masterKey = await _cryptoService.GetMasterKeyAsync(); - var encryptedKey = await _cryptoService.RsaEncryptAsync(masterKey.EncKey, publicKey); - var keyHash = await _stateService.GetKeyHashAsync(); + byte[] keyToEncrypt = null; EncString encryptedMasterPassword = null; - if (!string.IsNullOrEmpty(keyHash)) + + if (masterKey == null) { - encryptedMasterPassword = await _cryptoService.RsaEncryptAsync(Encoding.UTF8.GetBytes(keyHash), publicKey); + var userKey = await _cryptoService.GetUserKeyAsync(); + if (userKey == null) + { + throw new UserAndMasterKeysNullException(); + } + keyToEncrypt = userKey.Key; } + else + { + keyToEncrypt = masterKey.Key; + var keyHash = await _stateService.GetKeyHashAsync(); + if (!string.IsNullOrEmpty(keyHash)) + { + encryptedMasterPassword = await _cryptoService.RsaEncryptAsync(Encoding.UTF8.GetBytes(keyHash), publicKey); + } + } + + var encryptedKey = await _cryptoService.RsaEncryptAsync(keyToEncrypt, publicKey); var deviceId = await _appIdService.GetAppIdAsync(); var response = await _apiService.PutAuthRequestAsync(id, encryptedKey.EncryptedString, encryptedMasterPassword?.EncryptedString, deviceId, requestApproved); return await PopulateFingerprintPhraseAsync(response, await _stateService.GetEmailAsync()); diff --git a/src/Core/Services/CryptoService.cs b/src/Core/Services/CryptoService.cs index e0eaa8e8f..3f0974a49 100644 --- a/src/Core/Services/CryptoService.cs +++ b/src/Core/Services/CryptoService.cs @@ -120,8 +120,14 @@ namespace Bit.Core.Services var masterKey = await _stateService.GetMasterKeyAsync(userId); if (masterKey == null) { + var masterKeyDecrypted = await _stateService.GetKeyDecryptedAsync(userId); + if (masterKeyDecrypted == null) + { + return null; + } + // Migration support - masterKey = new MasterKey((await _stateService.GetKeyDecryptedAsync(userId)).Key); + masterKey = new MasterKey(masterKeyDecrypted.Key); if (masterKey != null) { await SetMasterKeyAsync(masterKey, userId);