mirror of
https://github.com/bitwarden/mobile
synced 2025-12-05 23:53:33 +00:00
[PM-2713] use new MakeMasterKey method
This commit is contained in:
@@ -295,19 +295,19 @@ namespace Bit.App.Pages
|
||||
}
|
||||
else
|
||||
{
|
||||
var key = await _cryptoService.MakeKeyAsync(MasterPassword, _email, kdfConfig);
|
||||
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.CompareAndUpdatePasswordHashAsync(MasterPassword, key);
|
||||
passwordValid = await _cryptoService.CompareAndUpdatePasswordHashAsync(MasterPassword, masterKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -316,7 +316,7 @@ namespace Bit.App.Pages
|
||||
var response = await _apiService.PostAccountVerifyPasswordAsync(request);
|
||||
enforcedMasterPasswordOptions = response.MasterPasswordPolicy;
|
||||
passwordValid = true;
|
||||
var localKeyHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.LocalAuthorization);
|
||||
var localKeyHash = await _cryptoService.HashPasswordAsync(MasterPassword, masterKey, HashPurpose.LocalAuthorization);
|
||||
await _cryptoService.SetPasswordHashAsync(localKeyHash);
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -327,13 +327,14 @@ namespace Bit.App.Pages
|
||||
}
|
||||
if (passwordValid)
|
||||
{
|
||||
// TODO(Jake): Update this to use new PinKeyEphemeral
|
||||
if (_isPinProtected)
|
||||
{
|
||||
var protectedPin = await _stateService.GetProtectedPinAsync();
|
||||
var encKey = await _cryptoService.GetEncKeyAsync(key);
|
||||
var encKey = await _cryptoService.GetEncKeyAsync(masterKey);
|
||||
var decPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), encKey);
|
||||
var pinKey = await _cryptoService.MakePinKeyAsync(decPin, _email, kdfConfig);
|
||||
await _stateService.SetPinProtectedKeyAsync(await _cryptoService.EncryptAsync(key.Key, pinKey));
|
||||
await _stateService.SetPinProtectedKeyAsync(await _cryptoService.EncryptAsync(masterKey.Key, pinKey));
|
||||
}
|
||||
|
||||
if (await RequirePasswordChangeAsync(enforcedMasterPasswordOptions))
|
||||
@@ -345,7 +346,7 @@ namespace Bit.App.Pages
|
||||
|
||||
MasterPassword = string.Empty;
|
||||
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
|
||||
await SetKeyAndContinueAsync(key);
|
||||
await SetKeyAndContinueAsync(masterKey);
|
||||
|
||||
// Re-enable biometrics
|
||||
if (BiometricLock & !BiometricIntegrityValid)
|
||||
@@ -447,6 +448,7 @@ namespace Bit.App.Pages
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(Jake): Update to store UserKey
|
||||
private async Task SetKeyAndContinueAsync(SymmetricCryptoKey key)
|
||||
{
|
||||
var hasKey = await _cryptoService.HasKeyAsync();
|
||||
|
||||
@@ -177,9 +177,9 @@ 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 masterKey = await _cryptoService.MakeMasterKeyAsync(MasterPassword, Email, kdfConfig);
|
||||
var encKey = await _cryptoService.MakeEncKeyAsync(masterKey);
|
||||
var hashedPassword = await _cryptoService.HashPasswordAsync(MasterPassword, masterKey);
|
||||
var keys = await _cryptoService.MakeKeyPairAsync(encKey.Item1);
|
||||
var request = new RegisterRequest
|
||||
{
|
||||
|
||||
@@ -165,19 +165,19 @@ 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 masterKey = await _cryptoService.MakeMasterKeyAsync(MasterPassword, email, kdfConfig);
|
||||
var masterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, masterKey, HashPurpose.ServerAuthorization);
|
||||
var localMasterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, masterKey, HashPurpose.LocalAuthorization);
|
||||
|
||||
Tuple<SymmetricCryptoKey, EncString> encKey;
|
||||
var existingEncKey = await _cryptoService.GetEncKeyAsync();
|
||||
if (existingEncKey == null)
|
||||
{
|
||||
encKey = await _cryptoService.MakeEncKeyAsync(key);
|
||||
encKey = await _cryptoService.MakeEncKeyAsync(masterKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
encKey = await _cryptoService.RemakeEncKeyAsync(key);
|
||||
encKey = await _cryptoService.RemakeEncKeyAsync(masterKey);
|
||||
}
|
||||
|
||||
var keys = await _cryptoService.MakeKeyPairAsync(encKey.Item1);
|
||||
@@ -204,7 +204,7 @@ namespace Bit.App.Pages
|
||||
// Set Password and relevant information
|
||||
await _apiService.SetPasswordAsync(request);
|
||||
await _stateService.SetKdfConfigurationAsync(kdfConfig);
|
||||
await _cryptoService.SetKeyAsync(key);
|
||||
await _cryptoService.SetKeyAsync(masterKey);
|
||||
await _cryptoService.SetPasswordHashAsync(localMasterPasswordHash);
|
||||
await _cryptoService.SetEncKeyAsync(encKey.Item2.EncryptedString);
|
||||
await _cryptoService.SetPrivateKeyAsync(keys.Item2.EncryptedString);
|
||||
|
||||
@@ -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);
|
||||
var newEncKey = await _cryptoService.RemakeEncKeyAsync(masterKey);
|
||||
|
||||
// Initiate API action
|
||||
try
|
||||
|
||||
@@ -69,7 +69,6 @@ namespace Bit.Core.Abstractions
|
||||
Task<bool> HasEncKeyAsync();
|
||||
Task<bool> HasKeyAsync(string userId = null);
|
||||
Task<Tuple<SymmetricCryptoKey, EncString>> MakeEncKeyAsync(SymmetricCryptoKey key);
|
||||
Task<SymmetricCryptoKey> MakeKeyAsync(string password, string salt, KdfConfig config);
|
||||
Task<SymmetricCryptoKey> MakeKeyFromPinAsync(string pin, string salt, KdfConfig config, EncString protectedKeyEs = null);
|
||||
// TODO(Jake): This isn't used, delete
|
||||
Task<Tuple<EncString, SymmetricCryptoKey>> MakeShareKeyAsync();
|
||||
|
||||
@@ -356,7 +356,7 @@ namespace Bit.Core.Services
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return await _cryptoService.MakeKeyAsync(masterPassword, email, kdfConfig);
|
||||
return await _cryptoService.MakeMasterKeyAsync(masterPassword, email, kdfConfig);
|
||||
}
|
||||
|
||||
private async Task<AuthResult> LogInHelperAsync(string email, string hashedPassword, string localHashedPassword,
|
||||
@@ -511,11 +511,11 @@ namespace Bit.Core.Services
|
||||
{
|
||||
// SSO Key Connector Onboarding
|
||||
var password = await _cryptoFunctionService.RandomBytesAsync(64);
|
||||
var k = await _cryptoService.MakeKeyAsync(Convert.ToBase64String(password), _tokenService.GetEmail(), tokenResponse.KdfConfig);
|
||||
var keyConnectorRequest = new KeyConnectorUserKeyRequest(k.EncKeyB64);
|
||||
await _cryptoService.SetKeyAsync(k);
|
||||
var masterKey = await _cryptoService.MakeMasterKeyAsync(Convert.ToBase64String(password), _tokenService.GetEmail(), tokenResponse.KdfConfig);
|
||||
var keyConnectorRequest = new KeyConnectorUserKeyRequest(masterKey.EncKeyB64);
|
||||
await _cryptoService.SetKeyAsync(masterKey);
|
||||
|
||||
var encKey = await _cryptoService.MakeEncKeyAsync(k);
|
||||
var encKey = await _cryptoService.MakeEncKeyAsync(masterKey);
|
||||
await _cryptoService.SetEncKeyAsync(encKey.Item2.EncryptedString);
|
||||
var keyPair = await _cryptoService.MakeKeyPairAsync();
|
||||
|
||||
|
||||
@@ -843,6 +843,54 @@ namespace Bit.Core.Services
|
||||
return new Tuple<T, EncString>(new SymmetricCryptoKey(encKey) as T, encKeyEnc);
|
||||
}
|
||||
|
||||
private async Task<SymmetricCryptoKey> MakeKeyAsync(string password, string salt, KdfConfig kdfConfig)
|
||||
{
|
||||
byte[] key = null;
|
||||
if (kdfConfig.Type == null || kdfConfig.Type == KdfType.PBKDF2_SHA256)
|
||||
{
|
||||
var iterations = kdfConfig.Iterations.GetValueOrDefault(5000);
|
||||
if (iterations < 5000)
|
||||
{
|
||||
throw new Exception("PBKDF2 iteration minimum is 5000.");
|
||||
}
|
||||
key = await _cryptoFunctionService.Pbkdf2Async(password, salt,
|
||||
CryptoHashAlgorithm.Sha256, iterations);
|
||||
}
|
||||
else if (kdfConfig.Type == KdfType.Argon2id)
|
||||
{
|
||||
var iterations = kdfConfig.Iterations.GetValueOrDefault(Constants.Argon2Iterations);
|
||||
var memory = kdfConfig.Memory.GetValueOrDefault(Constants.Argon2MemoryInMB) * 1024;
|
||||
var parallelism = kdfConfig.Parallelism.GetValueOrDefault(Constants.Argon2Parallelism);
|
||||
|
||||
if (kdfConfig.Iterations < 2)
|
||||
{
|
||||
throw new Exception("Argon2 iterations minimum is 2");
|
||||
}
|
||||
|
||||
if (kdfConfig.Memory < 16)
|
||||
{
|
||||
throw new Exception("Argon2 memory minimum is 16 MB");
|
||||
}
|
||||
else if (kdfConfig.Memory > 1024)
|
||||
{
|
||||
throw new Exception("Argon2 memory maximum is 1024 MB");
|
||||
}
|
||||
|
||||
if (kdfConfig.Parallelism < 1)
|
||||
{
|
||||
throw new Exception("Argon2 parallelism minimum is 1");
|
||||
}
|
||||
|
||||
var saltHash = await _cryptoFunctionService.HashAsync(salt, CryptoHashAlgorithm.Sha256);
|
||||
key = await _cryptoFunctionService.Argon2Async(password, saltHash, iterations, memory, parallelism);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Unknown kdf.");
|
||||
}
|
||||
return new SymmetricCryptoKey(key);
|
||||
}
|
||||
|
||||
private class EncryptedObject
|
||||
{
|
||||
public byte[] Iv { get; set; }
|
||||
@@ -1049,53 +1097,6 @@ namespace Bit.Core.Services
|
||||
await SetKeyAsync(key);
|
||||
}
|
||||
|
||||
public async Task<SymmetricCryptoKey> MakeKeyAsync(string password, string salt, KdfConfig kdfConfig)
|
||||
{
|
||||
byte[] key = null;
|
||||
if (kdfConfig.Type == null || kdfConfig.Type == KdfType.PBKDF2_SHA256)
|
||||
{
|
||||
var iterations = kdfConfig.Iterations.GetValueOrDefault(5000);
|
||||
if (iterations < 5000)
|
||||
{
|
||||
throw new Exception("PBKDF2 iteration minimum is 5000.");
|
||||
}
|
||||
key = await _cryptoFunctionService.Pbkdf2Async(password, salt,
|
||||
CryptoHashAlgorithm.Sha256, iterations);
|
||||
}
|
||||
else if (kdfConfig.Type == KdfType.Argon2id)
|
||||
{
|
||||
var iterations = kdfConfig.Iterations.GetValueOrDefault(Constants.Argon2Iterations);
|
||||
var memory = kdfConfig.Memory.GetValueOrDefault(Constants.Argon2MemoryInMB) * 1024;
|
||||
var parallelism = kdfConfig.Parallelism.GetValueOrDefault(Constants.Argon2Parallelism);
|
||||
|
||||
if (kdfConfig.Iterations < 2)
|
||||
{
|
||||
throw new Exception("Argon2 iterations minimum is 2");
|
||||
}
|
||||
|
||||
if (kdfConfig.Memory < 16)
|
||||
{
|
||||
throw new Exception("Argon2 memory minimum is 16 MB");
|
||||
}
|
||||
else if (kdfConfig.Memory > 1024)
|
||||
{
|
||||
throw new Exception("Argon2 memory maximum is 1024 MB");
|
||||
}
|
||||
|
||||
if (kdfConfig.Parallelism < 1)
|
||||
{
|
||||
throw new Exception("Argon2 parallelism minimum is 1");
|
||||
}
|
||||
|
||||
var saltHash = await _cryptoFunctionService.HashAsync(salt, CryptoHashAlgorithm.Sha256);
|
||||
key = await _cryptoFunctionService.Argon2Async(password, saltHash, iterations, memory, parallelism);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Unknown kdf.");
|
||||
}
|
||||
return new SymmetricCryptoKey(key);
|
||||
}
|
||||
|
||||
public async Task<SymmetricCryptoKey> MakeKeyFromPinAsync(string pin, string salt,
|
||||
KdfConfig config, EncString protectedKeyCs = null)
|
||||
|
||||
Reference in New Issue
Block a user