1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-16 00:03:22 +00:00

[PM-2713] fix casting issues and pin

This commit is contained in:
Jacob Fink
2023-07-20 13:57:32 -04:00
parent 0da3d25955
commit 813ac841c6
4 changed files with 26 additions and 23 deletions

View File

@@ -439,18 +439,18 @@ namespace Bit.App.Pages
var email = await _stateService.GetEmailAsync(); var email = await _stateService.GetEmailAsync();
var pinKey = await _cryptoService.MakePinKeyAsync(pin, email, kdfConfig); var pinKey = await _cryptoService.MakePinKeyAsync(pin, email, kdfConfig);
var userKey = await _cryptoService.GetUserKeyAsync(); var userKey = await _cryptoService.GetUserKeyAsync();
var pinProtectedKey = await _cryptoService.EncryptAsync(userKey.Key, pinKey); var protectedPinKey = await _cryptoService.EncryptAsync(userKey.Key, pinKey);
var encPin = await _cryptoService.EncryptAsync(pin); var encPin = await _cryptoService.EncryptAsync(pin);
await _stateService.SetProtectedPinAsync(encPin.EncryptedString); await _stateService.SetProtectedPinAsync(encPin.EncryptedString);
if (masterPassOnRestart) if (masterPassOnRestart)
{ {
await _stateService.SetUserKeyPinEphemeralAsync(pinProtectedKey); await _stateService.SetUserKeyPinEphemeralAsync(protectedPinKey);
} }
else else
{ {
await _stateService.SetUserKeyPinAsync(pinProtectedKey); await _stateService.SetUserKeyPinAsync(protectedPinKey);
} }
} }
else else

View File

@@ -146,7 +146,7 @@ namespace Bit.Core.Services
public async Task<Tuple<UserKey, EncString>> EncryptUserKeyWithMasterKeyAsync(MasterKey masterKey, UserKey userKey = null) public async Task<Tuple<UserKey, EncString>> EncryptUserKeyWithMasterKeyAsync(MasterKey masterKey, UserKey userKey = null)
{ {
userKey ??= await GetUserKeyAsync(); userKey ??= await GetUserKeyAsync();
return await BuildProtectedSymmetricKey<UserKey>(masterKey, userKey.Key); return await BuildProtectedSymmetricKey(masterKey, userKey.Key, keyBytes => new UserKey(keyBytes));
} }
public async Task<UserKey> DecryptUserKeyWithMasterKeyAsync(MasterKey masterKey, EncString encUserKey = null, string userId = null) public async Task<UserKey> DecryptUserKeyWithMasterKeyAsync(MasterKey masterKey, EncString encUserKey = null, string userId = null)
@@ -174,7 +174,7 @@ namespace Bit.Core.Services
} }
else if (encUserKey.EncryptionType == EncryptionType.AesCbc256_HmacSha256_B64) else if (encUserKey.EncryptionType == EncryptionType.AesCbc256_HmacSha256_B64)
{ {
var newKey = await StretchKeyAsync(masterKey); var newKey = await StretchKeyAsync(masterKey, keyBytes => new MasterKey(keyBytes));
decUserKey = await DecryptToBytesAsync(encUserKey, newKey); decUserKey = await DecryptToBytesAsync(encUserKey, newKey);
} }
else else
@@ -197,7 +197,7 @@ namespace Bit.Core.Services
} }
var newSymKey = await _cryptoFunctionService.RandomBytesAsync(64); var newSymKey = await _cryptoFunctionService.RandomBytesAsync(64);
return await BuildProtectedSymmetricKey<SymmetricCryptoKey>(key, newSymKey); return await BuildProtectedSymmetricKey(key, newSymKey, keyBytes => new SymmetricCryptoKey(keyBytes));
} }
public async Task<Tuple<SymmetricCryptoKey, EncString>> MakeDataEncKeyAsync(OrgKey key) public async Task<Tuple<SymmetricCryptoKey, EncString>> MakeDataEncKeyAsync(OrgKey key)
@@ -208,7 +208,7 @@ namespace Bit.Core.Services
} }
var newSymKey = await _cryptoFunctionService.RandomBytesAsync(64); var newSymKey = await _cryptoFunctionService.RandomBytesAsync(64);
return await BuildProtectedSymmetricKey<SymmetricCryptoKey>(key, newSymKey); return await BuildProtectedSymmetricKey(key, newSymKey, keyBytes => new SymmetricCryptoKey(keyBytes));
} }
public async Task<string> HashMasterKeyAsync(string password, MasterKey masterKey, HashPurpose hashPurpose = HashPurpose.ServerAuthorization) public async Task<string> HashMasterKeyAsync(string password, MasterKey masterKey, HashPurpose hashPurpose = HashPurpose.ServerAuthorization)
@@ -423,7 +423,7 @@ namespace Bit.Core.Services
public async Task<PinKey> MakePinKeyAsync(string pin, string salt, KdfConfig config) public async Task<PinKey> MakePinKeyAsync(string pin, string salt, KdfConfig config)
{ {
var pinKey = await MakeKeyAsync(pin, salt, config, keyBytes => new PinKey(keyBytes)); var pinKey = await MakeKeyAsync(pin, salt, config, keyBytes => new PinKey(keyBytes));
return await StretchKeyAsync(pinKey) as PinKey; return await StretchKeyAsync(pinKey, keyBytes => new PinKey(keyBytes));
} }
public Task ClearPinKeysAsync(string userId = null) public Task ClearPinKeysAsync(string userId = null)
@@ -819,14 +819,16 @@ namespace Bit.Core.Services
return key; return key;
} }
private async Task<SymmetricCryptoKey> StretchKeyAsync(SymmetricCryptoKey key) // TODO: This needs to be moved into SymmetricCryptoKey model to remove the keyCreator hack
private async Task<TKey> StretchKeyAsync<TKey>(SymmetricCryptoKey key, Func<byte[], TKey> keyCreator)
where TKey : SymmetricCryptoKey
{ {
var newKey = new byte[64]; var newKey = new byte[64];
var enc = await _cryptoFunctionService.HkdfExpandAsync(key.Key, Encoding.UTF8.GetBytes("enc"), 32, HkdfAlgorithm.Sha256); var enc = await _cryptoFunctionService.HkdfExpandAsync(key.Key, Encoding.UTF8.GetBytes("enc"), 32, HkdfAlgorithm.Sha256);
Buffer.BlockCopy(enc, 0, newKey, 0, 32); Buffer.BlockCopy(enc, 0, newKey, 0, 32);
var mac = await _cryptoFunctionService.HkdfExpandAsync(key.Key, Encoding.UTF8.GetBytes("mac"), 32, HkdfAlgorithm.Sha256); var mac = await _cryptoFunctionService.HkdfExpandAsync(key.Key, Encoding.UTF8.GetBytes("mac"), 32, HkdfAlgorithm.Sha256);
Buffer.BlockCopy(mac, 0, newKey, 32, 32); Buffer.BlockCopy(mac, 0, newKey, 32, 32);
return new SymmetricCryptoKey(newKey); return keyCreator(newKey);
} }
private List<string> HashPhrase(byte[] hash, int minimumEntropy = 64) private List<string> HashPhrase(byte[] hash, int minimumEntropy = 64)
@@ -853,13 +855,14 @@ namespace Bit.Core.Services
return phrase; return phrase;
} }
private async Task<Tuple<T, EncString>> BuildProtectedSymmetricKey<T>(SymmetricCryptoKey key, // TODO: This needs to be moved into SymmetricCryptoKey model to remove the keyCreator hack
byte[] encKey) where T : SymmetricCryptoKey private async Task<Tuple<TKey, EncString>> BuildProtectedSymmetricKey<TKey>(SymmetricCryptoKey key,
byte[] encKey, Func<byte[], TKey> keyCreator) where TKey : SymmetricCryptoKey
{ {
EncString encKeyEnc = null; EncString encKeyEnc = null;
if (key.Key.Length == 32) if (key.Key.Length == 32)
{ {
var newKey = await StretchKeyAsync(key); var newKey = await StretchKeyAsync(key, keyCreator);
encKeyEnc = await EncryptAsync(encKey, newKey); encKeyEnc = await EncryptAsync(encKey, newKey);
} }
else if (key.Key.Length == 64) else if (key.Key.Length == 64)
@@ -870,10 +873,10 @@ namespace Bit.Core.Services
{ {
throw new Exception("Invalid key size."); throw new Exception("Invalid key size.");
} }
return new Tuple<T, EncString>(new SymmetricCryptoKey(encKey) as T, encKeyEnc); return new Tuple<TKey, EncString>(keyCreator(encKey), encKeyEnc);
} }
// TODO: This intantiator needs to be moved into each key type in order to get rid of the keyCreator hack // TODO: This needs to be moved into SymmetricCryptoKey model to remove the keyCreator hack
private async Task<TKey> MakeKeyAsync<TKey>(string password, string salt, KdfConfig kdfConfig, Func<byte[], TKey> keyCreator) private async Task<TKey> MakeKeyAsync<TKey>(string password, string salt, KdfConfig kdfConfig, Func<byte[], TKey> keyCreator)
where TKey : SymmetricCryptoKey where TKey : SymmetricCryptoKey
{ {

View File

@@ -312,18 +312,18 @@ namespace Bit.iOS.Core.Controllers
{ {
var masterKey = await _cryptoService.MakeMasterKeyAsync(inputtedValue, email, kdfConfig); var masterKey = await _cryptoService.MakeMasterKeyAsync(inputtedValue, email, kdfConfig);
var storedPasswordHash = await _cryptoService.GetPasswordHashAsync(); var storedPasswordHash = await _cryptoService.GetMasterKeyHashAsync();
if (storedPasswordHash == null) if (storedPasswordHash == null)
{ {
var oldKey = await _secureStorageService.GetAsync<string>("oldKey"); var oldKey = await _secureStorageService.GetAsync<string>("oldKey");
if (masterKey.KeyB64 == oldKey) if (masterKey.KeyB64 == oldKey)
{ {
var localPasswordHash = await _cryptoService.HashPasswordAsync(inputtedValue, masterKey, HashPurpose.LocalAuthorization); var localPasswordHash = await _cryptoService.HashMasterKeyAsync(inputtedValue, masterKey, HashPurpose.LocalAuthorization);
await _secureStorageService.RemoveAsync("oldKey"); await _secureStorageService.RemoveAsync("oldKey");
await _cryptoService.SetPasswordHashAsync(localPasswordHash); await _cryptoService.SetMasterKeyHashAsync(localPasswordHash);
} }
} }
var passwordValid = await _cryptoService.CompareAndUpdatePasswordHashAsync(inputtedValue, masterKey); var passwordValid = await _cryptoService.CompareAndUpdateKeyHashAsync(inputtedValue, masterKey);
if (passwordValid) if (passwordValid)
{ {
await AppHelpers.ResetInvalidUnlockAttemptsAsync(); await AppHelpers.ResetInvalidUnlockAttemptsAsync();

View File

@@ -285,18 +285,18 @@ namespace Bit.iOS.Core.Controllers
{ {
var masterKey = await _cryptoService.MakeMasterKeyAsync(inputtedValue, email, kdfConfig); var masterKey = await _cryptoService.MakeMasterKeyAsync(inputtedValue, email, kdfConfig);
var storedPasswordHash = await _cryptoService.GetPasswordHashAsync(); var storedPasswordHash = await _cryptoService.GetMasterKeyHashAsync();
if (storedPasswordHash == null) if (storedPasswordHash == null)
{ {
var oldKey = await _secureStorageService.GetAsync<string>("oldKey"); var oldKey = await _secureStorageService.GetAsync<string>("oldKey");
if (masterKey.KeyB64 == oldKey) if (masterKey.KeyB64 == oldKey)
{ {
var localPasswordHash = await _cryptoService.HashPasswordAsync(inputtedValue, masterKey, HashPurpose.LocalAuthorization); var localPasswordHash = await _cryptoService.HashMasterKeyAsync(inputtedValue, masterKey, HashPurpose.LocalAuthorization);
await _secureStorageService.RemoveAsync("oldKey"); await _secureStorageService.RemoveAsync("oldKey");
await _cryptoService.SetPasswordHashAsync(localPasswordHash); await _cryptoService.SetMasterKeyHashAsync(localPasswordHash);
} }
} }
var passwordValid = await _cryptoService.CompareAndUpdatePasswordHashAsync(inputtedValue, masterKey); var passwordValid = await _cryptoService.CompareAndUpdateKeyHashAsync(inputtedValue, masterKey);
if (passwordValid) if (passwordValid)
{ {
await AppHelpers.ResetInvalidUnlockAttemptsAsync(); await AppHelpers.ResetInvalidUnlockAttemptsAsync();