1
0
mirror of https://github.com/bitwarden/mobile synced 2026-02-11 13:53:18 +00:00

Use 2 iterations for local password hashing

This commit is contained in:
Thomas Rittson
2021-06-10 09:41:28 +10:00
parent aff8227989
commit 35aebaa3e0
8 changed files with 27 additions and 21 deletions

View File

@@ -241,25 +241,26 @@ namespace Bit.App.Pages
else
{
var key = await _cryptoService.MakeKeyAsync(MasterPassword, _email, kdf, kdfIterations);
var keyHash = await _cryptoService.HashPasswordAsync(MasterPassword, key);
var localKeyHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.LocalAuthorization);
var passwordValid = false;
if (keyHash != null)
if (localKeyHash != null)
{
var storedKeyHash = await _cryptoService.GetKeyHashAsync();
if (storedKeyHash != null)
{
passwordValid = storedKeyHash == keyHash;
passwordValid = storedKeyHash == localKeyHash;
}
else
{
await _deviceActionService.ShowLoadingAsync(AppResources.Loading);
var keyHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.ServerAuthorization);
var request = new PasswordVerificationRequest();
request.MasterPasswordHash = keyHash;
try
{
await _apiService.PostAccountVerifyPasswordAsync(request);
passwordValid = true;
await _cryptoService.SetKeyHashAsync(keyHash);
await _cryptoService.SetKeyHashAsync(localKeyHash);
}
catch (Exception e)
{

View File

@@ -138,7 +138,8 @@ namespace Bit.App.Pages
var kdfIterations = 100000;
var email = await _userService.GetEmailAsync();
var key = await _cryptoService.MakeKeyAsync(MasterPassword, email, kdf, kdfIterations);
var masterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, key);
var masterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.ServerAuthorization);
var localMasterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.LocalAuthorization);
Tuple<SymmetricCryptoKey, EncString> encKey;
var existingEncKey = await _cryptoService.GetEncKeyAsync();
@@ -174,7 +175,7 @@ namespace Bit.App.Pages
await _userService.SetInformationAsync(await _userService.GetUserIdAsync(),
await _userService.GetEmailAsync(), kdf, kdfIterations);
await _cryptoService.SetKeyAsync(key);
await _cryptoService.SetKeyHashAsync(masterPasswordHash);
await _cryptoService.SetKeyHashAsync(localMasterPasswordHash);
await _cryptoService.SetEncKeyAsync(encKey.Item2.EncryptedString);
await _cryptoService.SetEncPrivateKeyAsync(keys.Item2.EncryptedString);
await _deviceActionService.HideLoadingAsync();

View File

@@ -103,7 +103,7 @@ namespace Bit.App.Pages
return;
}
var keyHash = await _cryptoService.HashPasswordAsync(_masterPassword, null);
var keyHash = await _cryptoService.HashPasswordAsync(_masterPassword, null, Core.Enums.HashPurpose.LocalAuthorization);
MasterPassword = string.Empty;
var storedKeyHash = await _cryptoService.GetKeyHashAsync();

View File

@@ -29,7 +29,7 @@ namespace Bit.App.Services
return false;
};
var keyHash = await _cryptoService.HashPasswordAsync(password, null);
var keyHash = await _cryptoService.HashPasswordAsync(password, null, Core.Enums.HashPurpose.LocalAuthorization);
var storedKeyHash = await _cryptoService.GetKeyHashAsync();
if (storedKeyHash == null || keyHash == null || storedKeyHash != keyHash)

View File

@@ -31,7 +31,7 @@ namespace Bit.Core.Abstractions
Task<byte[]> GetPrivateKeyAsync();
Task<byte[]> GetPublicKeyAsync();
Task<bool> HasEncKeyAsync();
Task<string> HashPasswordAsync(string password, SymmetricCryptoKey key, HashPurpose? hashPurpose);
Task<string> HashPasswordAsync(string password, SymmetricCryptoKey key, HashPurpose hashPurpose = HashPurpose.ServerAuthorization);
Task<bool> HasKeyAsync();
Task<Tuple<SymmetricCryptoKey, EncString>> MakeEncKeyAsync(SymmetricCryptoKey key);
Task<SymmetricCryptoKey> MakeKeyAsync(string password, string salt, KdfType? kdf, int? kdfIterations);

View File

@@ -93,6 +93,7 @@ namespace Bit.Core.Services
public string Email { get; set; }
public string MasterPasswordHash { get; set; }
public string LocalMasterPasswordHash { get; set; }
public string Code { get; set; }
public string CodeVerifier { get; set; }
public string SsoRedirectUrl { get; set; }
@@ -123,7 +124,8 @@ namespace Bit.Core.Services
SelectedTwoFactorProviderType = null;
var key = await MakePreloginKeyAsync(masterPassword, email);
var hashedPassword = await _cryptoService.HashPasswordAsync(masterPassword, key);
return await LogInHelperAsync(email, hashedPassword, null, null, null, key, null, null, null);
var localHashedPassword = await _cryptoService.HashPasswordAsync(masterPassword, key, HashPurpose.LocalAuthorization);
return await LogInHelperAsync(email, hashedPassword, localHashedPassword, null, null, null, key, null, null, null);
}
public async Task<AuthResult> LogInSsoAsync(string code, string codeVerifier, string redirectUrl)
@@ -135,7 +137,7 @@ namespace Bit.Core.Services
public Task<AuthResult> LogInTwoFactorAsync(TwoFactorProviderType twoFactorProvider, string twoFactorToken,
bool? remember = null)
{
return LogInHelperAsync(Email, MasterPasswordHash, Code, CodeVerifier, SsoRedirectUrl, _key,
return LogInHelperAsync(Email, MasterPasswordHash, LocalMasterPasswordHash, Code, CodeVerifier, SsoRedirectUrl, _key,
twoFactorProvider, twoFactorToken, remember);
}
@@ -145,7 +147,8 @@ namespace Bit.Core.Services
SelectedTwoFactorProviderType = null;
var key = await MakePreloginKeyAsync(masterPassword, email);
var hashedPassword = await _cryptoService.HashPasswordAsync(masterPassword, key);
return await LogInHelperAsync(email, hashedPassword, null, null, null, key, twoFactorProvider,
var localHashedPassword = await _cryptoService.HashPasswordAsync(masterPassword, key, HashPurpose.LocalAuthorization);
return await LogInHelperAsync(email, hashedPassword, localHashedPassword, null, null, null, key, twoFactorProvider,
twoFactorToken, remember);
}
@@ -153,7 +156,7 @@ namespace Bit.Core.Services
TwoFactorProviderType twoFactorProvider, string twoFactorToken, bool? remember = null)
{
SelectedTwoFactorProviderType = null;
return await LogInHelperAsync(null, null, code, codeVerifier, redirectUrl, null, twoFactorProvider,
return await LogInHelperAsync(null, null, null, code, codeVerifier, redirectUrl, null, twoFactorProvider,
twoFactorToken, remember);
}
@@ -266,8 +269,8 @@ namespace Bit.Core.Services
return await _cryptoService.MakeKeyAsync(masterPassword, email, kdf, kdfIterations);
}
private async Task<AuthResult> LogInHelperAsync(string email, string hashedPassword, string code,
string codeVerifier, string redirectUrl, SymmetricCryptoKey key,
private async Task<AuthResult> LogInHelperAsync(string email, string hashedPassword, string localHashedPassword,
string code, string codeVerifier, string redirectUrl, SymmetricCryptoKey key,
TwoFactorProviderType? twoFactorProvider = null, string twoFactorToken = null, bool? remember = null)
{
var storedTwoFactorToken = await _tokenService.GetTwoFactorTokenAsync(email);
@@ -318,6 +321,7 @@ namespace Bit.Core.Services
var twoFactorResponse = response.Item2;
Email = email;
MasterPasswordHash = hashedPassword;
LocalMasterPasswordHash = localHashedPassword;
Code = code;
CodeVerifier = codeVerifier;
SsoRedirectUrl = redirectUrl;
@@ -339,7 +343,7 @@ namespace Bit.Core.Services
if (_setCryptoKeys)
{
await _cryptoService.SetKeyAsync(key);
await _cryptoService.SetKeyHashAsync(hashedPassword);
await _cryptoService.SetKeyHashAsync(localHashedPassword);
await _cryptoService.SetEncKeyAsync(tokenResponse.Key);
// User doesn't have a key pair yet (old account), let's generate one for them.

View File

@@ -433,7 +433,7 @@ namespace Bit.Core.Services
return new SymmetricCryptoKey(sendKey);
}
public async Task<string> HashPasswordAsync(string password, SymmetricCryptoKey key, HashPurpose? hashPurpose)
public async Task<string> HashPasswordAsync(string password, SymmetricCryptoKey key, HashPurpose hashPurpose = HashPurpose.ServerAuthorization)
{
if (key == null)
{

View File

@@ -175,7 +175,7 @@ namespace Bit.iOS.Core.Controllers
else
{
var key2 = await _cryptoService.MakeKeyAsync(inputtedValue, email, kdf, kdfIterations);
var keyHash = await _cryptoService.HashPasswordAsync(inputtedValue, key2);
var localKeyHash = await _cryptoService.HashPasswordAsync(inputtedValue, key2, HashPurpose.LocalAuthorization);
var storedKeyHash = await _cryptoService.GetKeyHashAsync();
if (storedKeyHash == null)
{
@@ -183,11 +183,11 @@ namespace Bit.iOS.Core.Controllers
if (key2.KeyB64 == oldKey)
{
await _secureStorageService.RemoveAsync("oldKey");
await _cryptoService.SetKeyHashAsync(keyHash);
storedKeyHash = keyHash;
await _cryptoService.SetKeyHashAsync(localKeyHash);
storedKeyHash = localKeyHash;
}
}
if (storedKeyHash != null && keyHash != null && storedKeyHash == keyHash)
if (storedKeyHash != null && localKeyHash != null && storedKeyHash == localKeyHash)
{
if (_pinSet.Item1)
{