1
0
mirror of https://github.com/bitwarden/mobile synced 2026-01-06 18:43:43 +00:00

[PM-1690] Added minimum server version restriction to cipher key encryption (#2463)

* PM-1690 added minimum server version restriction to cipher key encryption and also change the force key rotation flag

* PM-1690 Updated min server version for new cipher encryption key and fixed configService registration

* PM-1690 removed forcekeyrotation
This commit is contained in:
Federico Maccaroni
2023-05-23 17:48:58 +03:00
committed by GitHub
parent 1a0e9e961d
commit b150d883c0
4 changed files with 56 additions and 3 deletions

View File

@@ -64,6 +64,7 @@
public const int Argon2Parallelism = 4;
public const int MasterPasswordMinimumChars = 12;
public const int CipherKeyRandomBytesLength = 64;
public const string CipherKeyEncryptionMinServerVersion = "2023.5.0";
public static readonly string[] AndroidAllClearCipherCacheKeys =
{

View File

@@ -30,6 +30,7 @@ namespace Bit.Core.Services
private readonly IStorageService _storageService;
private readonly II18nService _i18nService;
private readonly Func<ISearchService> _searchService;
private readonly IConfigService _configService;
private readonly string _clearCipherCacheKey;
private readonly string[] _allClearCipherCacheKeys;
private Dictionary<string, HashSet<string>> _domainMatchBlacklist = new Dictionary<string, HashSet<string>>
@@ -48,6 +49,7 @@ namespace Bit.Core.Services
IStorageService storageService,
II18nService i18nService,
Func<ISearchService> searchService,
IConfigService configService,
string clearCipherCacheKey,
string[] allClearCipherCacheKeys)
{
@@ -59,6 +61,7 @@ namespace Bit.Core.Services
_storageService = storageService;
_i18nService = i18nService;
_searchService = searchService;
_configService = configService;
_clearCipherCacheKey = clearCipherCacheKey;
_allClearCipherCacheKeys = allClearCipherCacheKeys;
}
@@ -209,6 +212,11 @@ namespace Bit.Core.Services
}
}
if (!await ShouldUseCipherKeyEncryptionAsync())
{
return key;
}
if (cipherView.Key != null)
{
cipher.Key = await _cryptoService.EncryptAsync(cipherView.Key.Key, key);
@@ -220,12 +228,22 @@ namespace Bit.Core.Services
var cfs = ServiceContainer.Resolve<ICryptoFunctionService>();
var newKey = new SymmetricCryptoKey(await cfs.RandomBytesAsync(Core.Constants.CipherKeyRandomBytesLength));
cipher.Key = await _cryptoService.EncryptAsync(newKey.Key, key);
return newKey;
#else
return key;
#endif
}
private async Task<bool> ShouldUseCipherKeyEncryptionAsync()
{
var config = await _configService.GetAsync();
return config != null
&&
VersionHelpers.IsServerVersionGreaterThanOrEqualTo(config.Version, Constants.CipherKeyEncryptionMinServerVersion);
}
public async Task<Cipher> GetAsync(string id)
{
var localData = await _stateService.GetLocalDataAsync();

View File

@@ -44,8 +44,9 @@ namespace Bit.Core.Utilities
var organizationService = new OrganizationService(stateService, apiService);
var settingsService = new SettingsService(stateService);
var fileUploadService = new FileUploadService(apiService);
var configService = new ConfigService(apiService, stateService, logger);
var cipherService = new CipherService(cryptoService, stateService, settingsService, apiService,
fileUploadService, storageService, i18nService, () => searchService, clearCipherCacheKey,
fileUploadService, storageService, i18nService, () => searchService, configService, clearCipherCacheKey,
allClearCipherCacheKeys);
var folderService = new FolderService(cryptoService, stateService, apiService, i18nService, cipherService);
var collectionService = new CollectionService(cryptoService, stateService, i18nService);
@@ -87,7 +88,6 @@ namespace Bit.Core.Utilities
var userVerificationService = new UserVerificationService(apiService, platformUtilsService, i18nService,
cryptoService);
var usernameGenerationService = new UsernameGenerationService(cryptoService, apiService, stateService);
var configService = new ConfigService(apiService, stateService, logger);
Register<IConditionedAwaiterManager>(conditionedRunner);
Register<ITokenService>("tokenService", tokenService);
@@ -95,6 +95,7 @@ namespace Bit.Core.Utilities
Register<IAppIdService>("appIdService", appIdService);
Register<IOrganizationService>("organizationService", organizationService);
Register<ISettingsService>("settingsService", settingsService);
Register<IConfigService>(configService);
Register<ICipherService>("cipherService", cipherService);
Register<IFolderService>("folderService", folderService);
Register<ICollectionService>("collectionService", collectionService);
@@ -113,7 +114,6 @@ namespace Bit.Core.Utilities
Register<IKeyConnectorService>("keyConnectorService", keyConnectorService);
Register<IUserVerificationService>("userVerificationService", userVerificationService);
Register<IUsernameGenerationService>(usernameGenerationService);
Register<IConfigService>(configService);
}
public static void Register<T>(string serviceName, T obj)

View File

@@ -0,0 +1,34 @@
using System;
namespace Bit.Core.Utilities
{
public static class VersionHelpers
{
private const char HOTFIX_SEPARATOR = '-';
/// <summary>
/// Compares two server versions and gets whether the <paramref name="targetVersion"/>
/// is greater than or equal to <paramref name="compareToVersion"/>.
/// WARNING: This doesn't take into account hotfix suffix.
/// </summary>
/// <param name="targetVersion">Version to compare</param>
/// <param name="compareToVersion">Version to compare against</param>
/// <returns>
/// <c>True</c> if <paramref name="targetVersion"/> is greater than or equal to <paramref name="compareToVersion"/>; <c>False</c> otherwise.
/// </returns>
public static bool IsServerVersionGreaterThanOrEqualTo(string targetVersion, string compareToVersion)
{
return GetServerVersionWithoutHotfix(targetVersion).CompareTo(GetServerVersionWithoutHotfix(compareToVersion)) >= 0;
}
public static Version GetServerVersionWithoutHotfix(string version)
{
if (string.IsNullOrWhiteSpace(version))
{
throw new ArgumentNullException(nameof(version));
}
return new Version(version.Split(HOTFIX_SEPARATOR)[0]);
}
}
}