mirror of
https://github.com/bitwarden/mobile
synced 2025-12-22 19:23:58 +00:00
[PM-2713] refresh pin key when setting user key
This commit is contained in:
@@ -9,7 +9,7 @@ namespace Bit.Core.Abstractions
|
|||||||
{
|
{
|
||||||
public interface ICryptoService
|
public interface ICryptoService
|
||||||
{
|
{
|
||||||
Task SetUserKeyAsync(UserKey userKey);
|
Task SetUserKeyAsync(UserKey userKey, string userId = null);
|
||||||
Task<UserKey> GetUserKeyAsync(string userId = null);
|
Task<UserKey> GetUserKeyAsync(string userId = null);
|
||||||
Task<bool> HasUserKeyAsync(string userId = null);
|
Task<bool> HasUserKeyAsync(string userId = null);
|
||||||
Task<UserKey> MakeUserKeyAsync();
|
Task<UserKey> MakeUserKeyAsync();
|
||||||
|
|||||||
@@ -44,18 +44,18 @@ namespace Bit.Core.Abstractions
|
|||||||
Task<bool> CanAccessPremiumAsync(string userId = null);
|
Task<bool> CanAccessPremiumAsync(string userId = null);
|
||||||
Task<string> GetProtectedPinAsync(string userId = null);
|
Task<string> GetProtectedPinAsync(string userId = null);
|
||||||
Task SetPersonalPremiumAsync(bool value, string userId = null);
|
Task SetPersonalPremiumAsync(bool value, string userId = null);
|
||||||
Task<string> GetUserKeyPin(string userId = null);
|
Task<string> GetUserKeyPinAsync(string userId = null);
|
||||||
Task SetUserKeyPin(string value, string userId = null);
|
Task SetUserKeyPinAsync(EncString value, string userId = null);
|
||||||
Task<EncString> GetUserKeyPinEphemeral(string userId = null);
|
Task<EncString> GetUserKeyPinEphemeralAsync(string userId = null);
|
||||||
Task SetUserKeyPinEphemeral(EncString value, string userId = null);
|
Task SetUserKeyPinEphemeralAsync(EncString value, string userId = null);
|
||||||
Task SetProtectedPinAsync(string value, string userId = null);
|
Task SetProtectedPinAsync(string value, string userId = null);
|
||||||
[Obsolete("Use GetUserKeyPin instead, left for migration purposes")]
|
[Obsolete("Use GetUserKeyPinAsync instead, left for migration purposes")]
|
||||||
Task<string> GetPinProtectedAsync(string userId = null);
|
Task<string> GetPinProtectedAsync(string userId = null);
|
||||||
[Obsolete("Use SetUserKeyPin instead")]
|
[Obsolete("Use SetUserKeyPinAsync instead")]
|
||||||
Task SetPinProtectedAsync(string value, string userId = null);
|
Task SetPinProtectedAsync(string value, string userId = null);
|
||||||
[Obsolete("Use GetUserKeyPinEphemeral instead, left for migration purposes")]
|
[Obsolete("Use GetUserKeyPinEphemeralAsync instead, left for migration purposes")]
|
||||||
Task<EncString> GetPinProtectedKeyAsync(string userId = null);
|
Task<EncString> GetPinProtectedKeyAsync(string userId = null);
|
||||||
[Obsolete("Use SetUserKeyPinEphemeral instead")]
|
[Obsolete("Use SetUserKeyPinEphemeralAsync instead")]
|
||||||
Task SetPinProtectedKeyAsync(EncString value, string userId = null);
|
Task SetPinProtectedKeyAsync(EncString value, string userId = null);
|
||||||
Task SetKdfConfigurationAsync(KdfConfig config, string userId = null);
|
Task SetKdfConfigurationAsync(KdfConfig config, string userId = null);
|
||||||
Task<string> GetKeyHashAsync(string userId = null);
|
Task<string> GetKeyHashAsync(string userId = null);
|
||||||
|
|||||||
@@ -36,9 +36,15 @@ namespace Bit.Core.Services
|
|||||||
_cryptoFunctionService = cryptoFunctionService;
|
_cryptoFunctionService = cryptoFunctionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SetUserKeyAsync(UserKey userKey)
|
public async Task SetUserKeyAsync(UserKey userKey, string userId = null)
|
||||||
{
|
{
|
||||||
await _stateService.SetUserKeyAsync(userKey);
|
await _stateService.SetUserKeyAsync(userKey, userId);
|
||||||
|
|
||||||
|
// Refresh the Pin Key if the user has a Pin set
|
||||||
|
if (await _stateService.GetProtectedPinAsync(userId) != null)
|
||||||
|
{
|
||||||
|
await StorePinKey(userKey, userId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<UserKey> GetUserKeyAsync(string userId = null)
|
public async Task<UserKey> GetUserKeyAsync(string userId = null)
|
||||||
@@ -610,6 +616,25 @@ namespace Bit.Core.Services
|
|||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
|
|
||||||
|
private async Task StorePinKey(UserKey userKey, string userId = null)
|
||||||
|
{
|
||||||
|
var pin = await DecryptToUtf8Async(new EncString(await _stateService.GetProtectedPinAsync(userId)));
|
||||||
|
var pinKey = await MakePinKeyAsync(
|
||||||
|
pin,
|
||||||
|
await _stateService.GetEmailAsync(userId),
|
||||||
|
await _stateService.GetActiveUserCustomDataAsync(a => new KdfConfig(a?.Profile))
|
||||||
|
);
|
||||||
|
var encPin = await EncryptAsync(userKey.Key, pinKey);
|
||||||
|
|
||||||
|
// TODO(Jake): Does this logic make sense? Should we save something in state to indicate the preference?
|
||||||
|
if (await _stateService.GetUserKeyPinAsync(userId) != null)
|
||||||
|
{
|
||||||
|
await _stateService.SetUserKeyPinAsync(encPin, userId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await _stateService.SetUserKeyPinEphemeralAsync(encPin, userId);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<EncryptedObject> AesEncryptAsync(byte[] data, SymmetricCryptoKey key)
|
private async Task<EncryptedObject> AesEncryptAsync(byte[] data, SymmetricCryptoKey key)
|
||||||
{
|
{
|
||||||
var obj = new EncryptedObject
|
var obj = new EncryptedObject
|
||||||
|
|||||||
@@ -396,25 +396,25 @@ namespace Bit.Core.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO(Jake): Does this need to be secure storage?
|
// TODO(Jake): Does this need to be secure storage?
|
||||||
public async Task<string> GetUserKeyPin(string userId = null)
|
public async Task<string> GetUserKeyPinAsync(string userId = null)
|
||||||
{
|
{
|
||||||
return await _storageMediatorService.GetAsync<string>(Constants.UserKeyPinKey(userId), false);
|
return await _storageMediatorService.GetAsync<string>(Constants.UserKeyPinKey(userId), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(Jake): Does this need to be secure storage?
|
// TODO(Jake): Does this need to be secure storage?
|
||||||
public async Task SetUserKeyPin(string value, string userId = null)
|
public async Task SetUserKeyPinAsync(EncString value, string userId = null)
|
||||||
{
|
{
|
||||||
await _storageMediatorService.SaveAsync(Constants.UserKeyPinKey(userId), value, false);
|
await _storageMediatorService.SaveAsync(Constants.UserKeyPinKey(userId), value.EncryptedString, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<EncString> GetUserKeyPinEphemeral(string userId = null)
|
public async Task<EncString> GetUserKeyPinEphemeralAsync(string userId = null)
|
||||||
{
|
{
|
||||||
return (await GetAccountAsync(
|
return (await GetAccountAsync(
|
||||||
ReconcileOptions(new StorageOptions { UserId = userId }, await GetDefaultInMemoryOptionsAsync())
|
ReconcileOptions(new StorageOptions { UserId = userId }, await GetDefaultInMemoryOptionsAsync())
|
||||||
))?.VolatileData?.UserKeyPinEphemeral;
|
))?.VolatileData?.UserKeyPinEphemeral;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SetUserKeyPinEphemeral(EncString value, string userId = null)
|
public async Task SetUserKeyPinEphemeralAsync(EncString value, string userId = null)
|
||||||
{
|
{
|
||||||
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
||||||
await GetDefaultInMemoryOptionsAsync());
|
await GetDefaultInMemoryOptionsAsync());
|
||||||
@@ -423,7 +423,7 @@ namespace Bit.Core.Services
|
|||||||
await SaveAccountAsync(account, reconciledOptions);
|
await SaveAccountAsync(account, reconciledOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Use GetUserKeyPin instead, left for migration purposes")]
|
[Obsolete("Use GetUserKeyPinAsync instead, left for migration purposes")]
|
||||||
public async Task<string> GetPinProtectedAsync(string userId = null)
|
public async Task<string> GetPinProtectedAsync(string userId = null)
|
||||||
{
|
{
|
||||||
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
||||||
@@ -431,7 +431,7 @@ namespace Bit.Core.Services
|
|||||||
return await GetValueAsync<string>(Constants.PinProtectedKey(reconciledOptions.UserId), reconciledOptions);
|
return await GetValueAsync<string>(Constants.PinProtectedKey(reconciledOptions.UserId), reconciledOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Use SetUserKeyPin instead")]
|
[Obsolete("Use SetUserKeyPinAsync instead")]
|
||||||
public async Task SetPinProtectedAsync(string value, string userId = null)
|
public async Task SetPinProtectedAsync(string value, string userId = null)
|
||||||
{
|
{
|
||||||
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
||||||
@@ -439,7 +439,7 @@ namespace Bit.Core.Services
|
|||||||
await SetValueAsync(Constants.PinProtectedKey(reconciledOptions.UserId), value, reconciledOptions);
|
await SetValueAsync(Constants.PinProtectedKey(reconciledOptions.UserId), value, reconciledOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Use GetUserKeyPinEphemeral instead, left for migration purposes")]
|
[Obsolete("Use GetUserKeyPinEphemeralAsync instead, left for migration purposes")]
|
||||||
public async Task<EncString> GetPinProtectedKeyAsync(string userId = null)
|
public async Task<EncString> GetPinProtectedKeyAsync(string userId = null)
|
||||||
{
|
{
|
||||||
return (await GetAccountAsync(
|
return (await GetAccountAsync(
|
||||||
@@ -447,7 +447,7 @@ namespace Bit.Core.Services
|
|||||||
))?.VolatileData?.PinProtectedKey;
|
))?.VolatileData?.PinProtectedKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Use SetUserKeyPinEphemeral instead")]
|
[Obsolete("Use SetUserKeyPinEphemeralAsync instead")]
|
||||||
public async Task SetPinProtectedKeyAsync(EncString value, string userId = null)
|
public async Task SetPinProtectedKeyAsync(EncString value, string userId = null)
|
||||||
{
|
{
|
||||||
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
||||||
|
|||||||
Reference in New Issue
Block a user