1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-11 13:53:29 +00:00

[PM-2713] rename key hash to password hash & begin add methods to crypto service

This commit is contained in:
Jacob Fink
2023-07-17 12:16:26 -04:00
parent 079e02e4e5
commit c1619536aa
7 changed files with 97 additions and 66 deletions

View File

@@ -296,13 +296,13 @@ namespace Bit.App.Pages
else else
{ {
var key = await _cryptoService.MakeKeyAsync(MasterPassword, _email, kdfConfig); var key = await _cryptoService.MakeKeyAsync(MasterPassword, _email, kdfConfig);
var storedKeyHash = await _cryptoService.GetKeyHashAsync(); var storedKeyHash = await _cryptoService.GetPasswordHashAsync();
var passwordValid = false; var passwordValid = false;
MasterPasswordPolicyOptions enforcedMasterPasswordOptions = null; MasterPasswordPolicyOptions enforcedMasterPasswordOptions = null;
if (storedKeyHash != null) if (storedKeyHash != null)
{ {
passwordValid = await _cryptoService.CompareAndUpdateKeyHashAsync(MasterPassword, key); passwordValid = await _cryptoService.CompareAndUpdatePasswordHashAsync(MasterPassword, key);
} }
else else
{ {
@@ -317,7 +317,7 @@ namespace Bit.App.Pages
enforcedMasterPasswordOptions = response.MasterPasswordPolicy; enforcedMasterPasswordOptions = response.MasterPasswordPolicy;
passwordValid = true; passwordValid = true;
var localKeyHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.LocalAuthorization); var localKeyHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.LocalAuthorization);
await _cryptoService.SetKeyHashAsync(localKeyHash); await _cryptoService.SetPasswordHashAsync(localKeyHash);
} }
catch (Exception e) catch (Exception e)
{ {

View File

@@ -205,7 +205,7 @@ namespace Bit.App.Pages
await _apiService.SetPasswordAsync(request); await _apiService.SetPasswordAsync(request);
await _stateService.SetKdfConfigurationAsync(kdfConfig); await _stateService.SetKdfConfigurationAsync(kdfConfig);
await _cryptoService.SetKeyAsync(key); await _cryptoService.SetKeyAsync(key);
await _cryptoService.SetKeyHashAsync(localMasterPasswordHash); await _cryptoService.SetPasswordHashAsync(localMasterPasswordHash);
await _cryptoService.SetEncKeyAsync(encKey.Item2.EncryptedString); await _cryptoService.SetEncKeyAsync(encKey.Item2.EncryptedString);
await _cryptoService.SetEncPrivateKeyAsync(keys.Item2.EncryptedString); await _cryptoService.SetEncPrivateKeyAsync(keys.Item2.EncryptedString);

View File

@@ -38,7 +38,7 @@ namespace Bit.App.Services
return false; return false;
}; };
return await _cryptoService.CompareAndUpdateKeyHashAsync(password, null); return await _cryptoService.CompareAndUpdatePasswordHashAsync(password, null);
} }
public async Task<bool> Enabled() public async Task<bool> Enabled()

View File

@@ -9,9 +9,21 @@ namespace Bit.Core.Abstractions
{ {
public interface ICryptoService public interface ICryptoService
{ {
Task SetUserKeyAsync(UserKey userKey);
Task<UserKey> GetUserKeyAsync(string userId = null);
Task<bool> HasUserKeyAsync(string userId = null);
Task ClearUserKeyAsync(string userId = null);
Task SetMasterKeyEncryptedUserKeyAsync(string value, string userId = null);
Task SetMasterKeyAsync(MasterKey masterKey, string userId = null);
Task<MasterKey> GetMasterKeyAsync(string userId = null);
Task ClearMasterKeyAsync(string userId = null);
Task SetPasswordHashAsync(string keyHash);
Task<string> GetPasswordHashAsync();
Task ClearPasswordHashAsync(string userId = null);
Task<bool> CompareAndUpdatePasswordHashAsync(string masterPassword, SymmetricCryptoKey key);
Task ClearEncKeyAsync(bool memoryOnly = false, string userId = null); Task ClearEncKeyAsync(bool memoryOnly = false, string userId = null);
Task ClearKeyAsync(string userId = null); Task ClearKeyAsync(string userId = null);
Task ClearKeyHashAsync(string userId = null);
Task ClearKeyPairAsync(bool memoryOnly = false, string userId = null); Task ClearKeyPairAsync(bool memoryOnly = false, string userId = null);
Task ClearKeysAsync(string userId = null); Task ClearKeysAsync(string userId = null);
Task ClearOrgKeysAsync(bool memoryOnly = false, string userId = null); Task ClearOrgKeysAsync(bool memoryOnly = false, string userId = null);
@@ -26,12 +38,10 @@ namespace Bit.Core.Abstractions
Task<SymmetricCryptoKey> GetEncKeyAsync(SymmetricCryptoKey key = null); Task<SymmetricCryptoKey> GetEncKeyAsync(SymmetricCryptoKey key = null);
Task<List<string>> GetFingerprintAsync(string userId, byte[] publicKey = null); Task<List<string>> GetFingerprintAsync(string userId, byte[] publicKey = null);
Task<SymmetricCryptoKey> GetKeyAsync(string userId = null); Task<SymmetricCryptoKey> GetKeyAsync(string userId = null);
Task<string> GetKeyHashAsync();
Task<SymmetricCryptoKey> GetOrgKeyAsync(string orgId); Task<SymmetricCryptoKey> GetOrgKeyAsync(string orgId);
Task<Dictionary<string, SymmetricCryptoKey>> GetOrgKeysAsync(); Task<Dictionary<string, SymmetricCryptoKey>> GetOrgKeysAsync();
Task<byte[]> GetPrivateKeyAsync(); Task<byte[]> GetPrivateKeyAsync();
Task<byte[]> GetPublicKeyAsync(); Task<byte[]> GetPublicKeyAsync();
Task<bool> CompareAndUpdateKeyHashAsync(string masterPassword, SymmetricCryptoKey key);
Task<bool> HasEncKeyAsync(); Task<bool> HasEncKeyAsync();
Task<string> HashPasswordAsync(string password, SymmetricCryptoKey key, HashPurpose hashPurpose = HashPurpose.ServerAuthorization); Task<string> HashPasswordAsync(string password, SymmetricCryptoKey key, HashPurpose hashPurpose = HashPurpose.ServerAuthorization);
Task<bool> HasKeyAsync(string userId = null); Task<bool> HasKeyAsync(string userId = null);
@@ -50,7 +60,6 @@ namespace Bit.Core.Abstractions
Task SetEncKeyAsync(string encKey); Task SetEncKeyAsync(string encKey);
Task SetEncPrivateKeyAsync(string encPrivateKey); Task SetEncPrivateKeyAsync(string encPrivateKey);
Task SetKeyAsync(SymmetricCryptoKey key); Task SetKeyAsync(SymmetricCryptoKey key);
Task SetKeyHashAsync(string keyHash);
Task SetOrgKeysAsync(IEnumerable<ProfileOrganizationResponse> orgs); Task SetOrgKeysAsync(IEnumerable<ProfileOrganizationResponse> orgs);
Task ToggleKeyAsync(); Task ToggleKeyAsync();
} }

View File

@@ -477,7 +477,7 @@ namespace Bit.Core.Services
if (localHashedPassword != null) if (localHashedPassword != null)
{ {
await _cryptoService.SetKeyHashAsync(localHashedPassword); await _cryptoService.SetPasswordHashAsync(localHashedPassword);
} }
if (code == null || tokenResponse.Key != null) if (code == null || tokenResponse.Key != null)

View File

@@ -21,7 +21,7 @@ namespace Bit.Core.Services
private SymmetricCryptoKey _encKey; private SymmetricCryptoKey _encKey;
private SymmetricCryptoKey _legacyEtmKey; private SymmetricCryptoKey _legacyEtmKey;
private string _keyHash; private string _passwordHash;
private byte[] _publicKey; private byte[] _publicKey;
private byte[] _privateKey; private byte[] _privateKey;
private Dictionary<string, SymmetricCryptoKey> _orgKeys; private Dictionary<string, SymmetricCryptoKey> _orgKeys;
@@ -36,22 +36,37 @@ namespace Bit.Core.Services
_cryptoFunctionService = cryptoFunctionService; _cryptoFunctionService = cryptoFunctionService;
} }
public async Task SetUserKeyAsync(UserKey key) public async Task SetUserKeyAsync(UserKey userKey)
{ {
await _stateService.SetUserKeyAsync(key); await _stateService.SetUserKeyAsync(userKey);
} }
public async Task<UserKey> GetUserKey(string userId = null) public async Task<UserKey> GetUserKeyAsync(string userId = null)
{ {
return await _stateService.GetUserKeyAsync(userId); return await _stateService.GetUserKeyAsync(userId);
} }
public async Task SetMasterKey(MasterKey masterKey, string userId = null) public async Task<bool> HasUserKeyAsync(string userId = null)
{
return await GetUserKeyAsync(userId) != null;
}
public async Task ClearUserKeyAsync(string userId = null)
{
await _stateService.SetUserKeyAsync(null, userId);
}
public async Task SetMasterKeyEncryptedUserKeyAsync(string value, string userId = null)
{
await _stateService.SetUserKeyMasterKeyAsync(value, userId);
}
public async Task SetMasterKeyAsync(MasterKey masterKey, string userId = null)
{ {
await _stateService.SetMasterKeyAsync(masterKey, userId); await _stateService.SetMasterKeyAsync(masterKey, userId);
} }
public async Task<MasterKey> GetMasterKey(string userId = null) public async Task<MasterKey> GetMasterKeyAsync(string userId = null)
{ {
var masterKey = await _stateService.GetMasterKeyAsync(userId); var masterKey = await _stateService.GetMasterKeyAsync(userId);
if (masterKey == null) if (masterKey == null)
@@ -59,12 +74,63 @@ namespace Bit.Core.Services
// Migration support // Migration support
var encMasterKey = await _stateService.GetKeyEncryptedAsync(userId); var encMasterKey = await _stateService.GetKeyEncryptedAsync(userId);
masterKey = new MasterKey(Convert.FromBase64String(encMasterKey)); masterKey = new MasterKey(Convert.FromBase64String(encMasterKey));
await this.SetMasterKey(masterKey, userId); await this.SetMasterKeyAsync(masterKey, userId);
} }
return masterKey; return masterKey;
} }
public async Task ClearMasterKeyAsync(string userId = null)
{
await _stateService.SetMasterKeyAsync(null, userId);
}
public async Task SetPasswordHashAsync(string keyHash)
{
_passwordHash = keyHash;
await _stateService.SetKeyHashAsync(keyHash);
}
public async Task<string> GetPasswordHashAsync()
{
if (_passwordHash != null)
{
return _passwordHash;
}
var passwordHash = await _stateService.GetKeyHashAsync();
if (passwordHash != null)
{
_passwordHash = passwordHash;
}
return _passwordHash;
}
public async Task ClearPasswordHashAsync(string userId = null)
{
_passwordHash = null;
await _stateService.SetKeyHashAsync(null, userId);
}
public async Task<bool> CompareAndUpdatePasswordHashAsync(string masterPassword, SymmetricCryptoKey key)
{
var storedPasswordHash = await GetPasswordHashAsync();
if (masterPassword != null && storedPasswordHash != null)
{
var localPasswordHash = await HashPasswordAsync(masterPassword, key, HashPurpose.LocalAuthorization);
if (localPasswordHash != null && storedPasswordHash == localPasswordHash)
{
return true;
}
var serverPasswordHash = await HashPasswordAsync(masterPassword, key, HashPurpose.ServerAuthorization);
if (serverPasswordHash != null & storedPasswordHash == serverPasswordHash)
{
await SetPasswordHashAsync(localPasswordHash);
return true;
}
}
return false;
}
public async Task SetKeyAsync(SymmetricCryptoKey key) public async Task SetKeyAsync(SymmetricCryptoKey key)
@@ -80,11 +146,6 @@ namespace Bit.Core.Services
await _stateService.SetKeyEncryptedAsync(key?.KeyB64); await _stateService.SetKeyEncryptedAsync(key?.KeyB64);
} }
public async Task SetPasswordHashAsync(string keyHash)
{
_keyHash = keyHash;
await _stateService.SetKeyHashAsync(keyHash);
}
public async Task SetEncKeyAsync(string encKey) public async Task SetEncKeyAsync(string encKey)
{ {
@@ -129,19 +190,6 @@ namespace Bit.Core.Services
return inMemoryKey; return inMemoryKey;
} }
public async Task<string> GetKeyHashAsync()
{
if (_keyHash != null)
{
return _keyHash;
}
var keyHash = await _stateService.GetKeyHashAsync();
if (keyHash != null)
{
_keyHash = keyHash;
}
return _keyHash;
}
public Task<SymmetricCryptoKey> GetEncKeyAsync(SymmetricCryptoKey key = null) public Task<SymmetricCryptoKey> GetEncKeyAsync(SymmetricCryptoKey key = null)
{ {
@@ -306,27 +354,6 @@ namespace Bit.Core.Services
return orgKeys[orgId]; return orgKeys[orgId];
} }
public async Task<bool> CompareAndUpdateKeyHashAsync(string masterPassword, SymmetricCryptoKey key)
{
var storedKeyHash = await GetKeyHashAsync();
if (masterPassword != null && storedKeyHash != null)
{
var localKeyHash = await HashPasswordAsync(masterPassword, key, HashPurpose.LocalAuthorization);
if (localKeyHash != null && storedKeyHash == localKeyHash)
{
return true;
}
var serverKeyHash = await HashPasswordAsync(masterPassword, key, HashPurpose.ServerAuthorization);
if (serverKeyHash != null & storedKeyHash == serverKeyHash)
{
await SetPasswordHashAsync(localKeyHash);
return true;
}
}
return false;
}
public async Task<bool> HasKeyAsync(string userId = null) public async Task<bool> HasKeyAsync(string userId = null)
{ {
@@ -347,11 +374,6 @@ namespace Bit.Core.Services
await _stateService.SetKeyEncryptedAsync(null, userId); await _stateService.SetKeyEncryptedAsync(null, userId);
} }
public async Task ClearKeyHashAsync(string userId = null)
{
_keyHash = null;
await _stateService.SetKeyHashAsync(null, userId);
}
public async Task ClearEncKeyAsync(bool memoryOnly = false, string userId = null) public async Task ClearEncKeyAsync(bool memoryOnly = false, string userId = null)
{ {
@@ -389,7 +411,7 @@ namespace Bit.Core.Services
{ {
_encKey = null; _encKey = null;
_legacyEtmKey = null; _legacyEtmKey = null;
_keyHash = null; _passwordHash = null;
_publicKey = null; _publicKey = null;
_privateKey = null; _privateKey = null;
_orgKeys = null; _orgKeys = null;
@@ -400,7 +422,7 @@ namespace Bit.Core.Services
await Task.WhenAll(new Task[] await Task.WhenAll(new Task[]
{ {
ClearKeyAsync(userId), ClearKeyAsync(userId),
ClearKeyHashAsync(userId), ClearPasswordHashAsync(userId),
ClearOrgKeysAsync(false, userId), ClearOrgKeysAsync(false, userId),
ClearEncKeyAsync(false, userId), ClearEncKeyAsync(false, userId),
ClearKeyPairAsync(false, userId), ClearKeyPairAsync(false, userId),
@@ -853,7 +875,7 @@ namespace Bit.Core.Services
private async Task<UserKey> GetUserKeyWithLegacySupport(string userId = null) private async Task<UserKey> GetUserKeyWithLegacySupport(string userId = null)
{ {
var userKey = await GetUserKey(); var userKey = await GetUserKeyAsync();
if (userKey != null) if (userKey != null)
{ {
return userKey; return userKey;
@@ -861,7 +883,7 @@ namespace Bit.Core.Services
// Legacy support: encryption used to be done with the master key (derived from master password). // Legacy support: encryption used to be done with the master key (derived from master password).
// Users who have not migrated will have a null user key and must use the master key instead. // Users who have not migrated will have a null user key and must use the master key instead.
return (SymmetricCryptoKey)await GetMasterKey() as UserKey; return (SymmetricCryptoKey)await GetMasterKeyAsync() as UserKey;
} }
private async Task<SymmetricCryptoKey> GetKeyForEncryptionAsync(SymmetricCryptoKey key = null) private async Task<SymmetricCryptoKey> GetKeyForEncryptionAsync(SymmetricCryptoKey key = null)

View File

@@ -44,7 +44,7 @@ namespace Bit.Core.Services
} }
else else
{ {
var passwordValid = await _cryptoService.CompareAndUpdateKeyHashAsync(secret, null); var passwordValid = await _cryptoService.CompareAndUpdatePasswordHashAsync(secret, null);
if (!passwordValid) if (!passwordValid)
{ {
await InvalidSecretErrorAsync(verificationType); await InvalidSecretErrorAsync(verificationType);