mirror of
https://github.com/bitwarden/mobile
synced 2026-01-08 03:23:23 +00:00
new enc key implementation
This commit is contained in:
@@ -6,8 +6,6 @@ using Bit.App.Models.Api;
|
||||
using Plugin.Settings.Abstractions;
|
||||
using Bit.App.Models;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Bit.App.Services
|
||||
{
|
||||
@@ -273,6 +271,11 @@ namespace Bit.App.Services
|
||||
|
||||
private async Task ProcessLoginSuccessAsync(SymmetricCryptoKey key, TokenResponse response)
|
||||
{
|
||||
if(response.Key != null)
|
||||
{
|
||||
_cryptoService.SetEncKey(new CipherString(response.PrivateKey));
|
||||
}
|
||||
|
||||
if(response.PrivateKey != null)
|
||||
{
|
||||
_cryptoService.SetPrivateKey(new CipherString(response.PrivateKey));
|
||||
|
||||
@@ -16,8 +16,8 @@ namespace Bit.App.Services
|
||||
public class CryptoService : ICryptoService
|
||||
{
|
||||
private const string KeyKey = "key";
|
||||
private const string PreviousKeyKey = "previousKey";
|
||||
private const string PrivateKeyKey = "encPrivateKey";
|
||||
private const string EncKeyKey = "encKey";
|
||||
private const string OrgKeysKey = "encOrgKeys";
|
||||
private const int InitializationVectorSize = 16;
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace Bit.App.Services
|
||||
private readonly ISecureStorageService _secureStorage;
|
||||
private readonly IKeyDerivationService _keyDerivationService;
|
||||
private SymmetricCryptoKey _key;
|
||||
private SymmetricCryptoKey _encKey;
|
||||
private SymmetricCryptoKey _legacyEtmKey;
|
||||
private SymmetricCryptoKey _previousKey;
|
||||
private IDictionary<string, SymmetricCryptoKey> _orgKeys;
|
||||
@@ -63,7 +64,6 @@ namespace Bit.App.Services
|
||||
}
|
||||
else
|
||||
{
|
||||
PreviousKey = _key;
|
||||
_secureStorage.Delete(KeyKey);
|
||||
}
|
||||
|
||||
@@ -72,46 +72,27 @@ namespace Bit.App.Services
|
||||
}
|
||||
}
|
||||
|
||||
public SymmetricCryptoKey PreviousKey
|
||||
public SymmetricCryptoKey EncKey
|
||||
{
|
||||
get
|
||||
{
|
||||
if(_previousKey == null && _secureStorage.Contains(PreviousKeyKey))
|
||||
if(_encKey == null && _settings.Contains(EncKeyKey))
|
||||
{
|
||||
var keyBytes = _secureStorage.Retrieve(PreviousKeyKey);
|
||||
if(keyBytes != null)
|
||||
var encKey = _settings.GetValueOrDefault<string>(EncKeyKey);
|
||||
var encKeyCs = new CipherString(encKey);
|
||||
try
|
||||
{
|
||||
_previousKey = new SymmetricCryptoKey(keyBytes);
|
||||
var decBytes = DecryptToBytes(encKeyCs, Key);
|
||||
_encKey = new SymmetricCryptoKey(decBytes);
|
||||
}
|
||||
catch
|
||||
{
|
||||
_encKey = null;
|
||||
Debug.WriteLine($"Cannot set enc key. Decryption failed.");
|
||||
}
|
||||
}
|
||||
|
||||
return _previousKey;
|
||||
}
|
||||
private set
|
||||
{
|
||||
if(value != null)
|
||||
{
|
||||
_secureStorage.Store(PreviousKeyKey, value.Key);
|
||||
_previousKey = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool KeyChanged
|
||||
{
|
||||
get
|
||||
{
|
||||
if(Key == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(PreviousKey == null)
|
||||
{
|
||||
return Key != null;
|
||||
}
|
||||
|
||||
return !PreviousKey.Key.SequenceEqual(Key.Key);
|
||||
return _encKey;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,6 +150,20 @@ namespace Bit.App.Services
|
||||
}
|
||||
}
|
||||
|
||||
public void SetEncKey(CipherString encKeyEnc)
|
||||
{
|
||||
if(encKeyEnc != null)
|
||||
{
|
||||
_settings.AddOrUpdateValue(EncKeyKey, encKeyEnc.EncryptedString);
|
||||
}
|
||||
else if(_settings.Contains(EncKeyKey))
|
||||
{
|
||||
_settings.Remove(EncKeyKey);
|
||||
}
|
||||
|
||||
_encKey = null;
|
||||
}
|
||||
|
||||
public void SetPrivateKey(CipherString privateKeyEnc)
|
||||
{
|
||||
if(privateKeyEnc != null)
|
||||
@@ -178,12 +173,9 @@ namespace Bit.App.Services
|
||||
else if(_settings.Contains(PrivateKeyKey))
|
||||
{
|
||||
_settings.Remove(PrivateKeyKey);
|
||||
_privateKey = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_privateKey = null;
|
||||
}
|
||||
|
||||
_privateKey = null;
|
||||
}
|
||||
|
||||
public void SetOrgKeys(ProfileResponse profile)
|
||||
@@ -234,13 +226,25 @@ namespace Bit.App.Services
|
||||
SetOrgKeys((Dictionary<string, string>)null);
|
||||
Key = null;
|
||||
SetPrivateKey(null);
|
||||
SetEncKey(null);
|
||||
}
|
||||
|
||||
public CipherString Encrypt(string plaintextValue, SymmetricCryptoKey key = null)
|
||||
{
|
||||
if(plaintextValue == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(plaintextValue));
|
||||
}
|
||||
|
||||
var plaintextBytes = Encoding.UTF8.GetBytes(plaintextValue);
|
||||
return Encrypt(plaintextBytes, key);
|
||||
}
|
||||
|
||||
public CipherString Encrypt(byte[] plainBytes, SymmetricCryptoKey key = null)
|
||||
{
|
||||
if(key == null)
|
||||
{
|
||||
key = Key;
|
||||
key = EncKey ?? Key;
|
||||
}
|
||||
|
||||
if(key == null)
|
||||
@@ -248,17 +252,15 @@ namespace Bit.App.Services
|
||||
throw new ArgumentNullException(nameof(key));
|
||||
}
|
||||
|
||||
if(plaintextValue == null)
|
||||
if(plainBytes == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(plaintextValue));
|
||||
throw new ArgumentNullException(nameof(plainBytes));
|
||||
}
|
||||
|
||||
var plaintextBytes = Encoding.UTF8.GetBytes(plaintextValue);
|
||||
|
||||
var provider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
|
||||
var cryptoKey = provider.CreateSymmetricKey(key.EncKey);
|
||||
var iv = WinRTCrypto.CryptographicBuffer.GenerateRandom(provider.BlockLength);
|
||||
var encryptedBytes = WinRTCrypto.CryptographicEngine.Encrypt(cryptoKey, plaintextBytes, iv);
|
||||
var encryptedBytes = WinRTCrypto.CryptographicEngine.Encrypt(cryptoKey, plainBytes, iv);
|
||||
var mac = key.MacKey != null ? ComputeMacBase64(encryptedBytes, iv, key.MacKey) : null;
|
||||
|
||||
return new CipherString(key.EncryptionType, Convert.ToBase64String(iv),
|
||||
@@ -283,7 +285,7 @@ namespace Bit.App.Services
|
||||
{
|
||||
if(key == null)
|
||||
{
|
||||
key = Key;
|
||||
key = EncKey ?? Key;
|
||||
}
|
||||
|
||||
if(key == null)
|
||||
@@ -448,7 +450,7 @@ namespace Bit.App.Services
|
||||
{
|
||||
if(key == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(Key));
|
||||
throw new ArgumentNullException(nameof(key));
|
||||
}
|
||||
|
||||
if(password == null)
|
||||
@@ -466,5 +468,11 @@ namespace Bit.App.Services
|
||||
var hash = HashPassword(key, password);
|
||||
return Convert.ToBase64String(hash);
|
||||
}
|
||||
|
||||
public CipherString MakeEncKey(SymmetricCryptoKey key)
|
||||
{
|
||||
var bytes = WinRTCrypto.CryptographicBuffer.GenerateRandom(512 / 8);
|
||||
return Encrypt(bytes, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ using System.Collections.Generic;
|
||||
using Xamarin.Forms;
|
||||
using Newtonsoft.Json;
|
||||
using Bit.App.Models;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Bit.App.Services
|
||||
{
|
||||
@@ -203,7 +202,7 @@ namespace Bit.App.Services
|
||||
return false;
|
||||
}
|
||||
|
||||
await SyncOrgKeysAsync(profile.Result);
|
||||
await SyncProfileKeysAsync(profile.Result);
|
||||
|
||||
SyncCompleted(true);
|
||||
return true;
|
||||
@@ -258,11 +257,11 @@ namespace Bit.App.Services
|
||||
var loginTask = SyncLoginsAsync(loginsDict);
|
||||
var folderTask = SyncFoldersAsync(foldersDict);
|
||||
var domainsTask = SyncDomainsAsync(domains.Result);
|
||||
var orgKeysTask = SyncOrgKeysAsync(profile.Result);
|
||||
await Task.WhenAll(loginTask, folderTask, domainsTask, orgKeysTask).ConfigureAwait(false);
|
||||
var profileTask = SyncProfileKeysAsync(profile.Result);
|
||||
await Task.WhenAll(loginTask, folderTask, domainsTask, profileTask).ConfigureAwait(false);
|
||||
|
||||
if(folderTask.Exception != null || loginTask.Exception != null || domainsTask.Exception != null ||
|
||||
orgKeysTask.Exception != null)
|
||||
profileTask.Exception != null)
|
||||
{
|
||||
SyncCompleted(false);
|
||||
return false;
|
||||
@@ -397,23 +396,20 @@ namespace Bit.App.Services
|
||||
catch(SQLite.SQLiteException) { }
|
||||
}
|
||||
|
||||
private async Task SyncOrgKeysAsync(ProfileResponse profile)
|
||||
private Task SyncProfileKeysAsync(ProfileResponse profile)
|
||||
{
|
||||
if(_cryptoService.PrivateKey == null && (profile.Organizations?.Any() ?? false))
|
||||
if(!string.IsNullOrWhiteSpace(profile.Key))
|
||||
{
|
||||
var keys = await _accountsApiRepository.GetKeys();
|
||||
if(!CheckSuccess(keys))
|
||||
{
|
||||
return;
|
||||
}
|
||||
_cryptoService.SetEncKey(new CipherString(profile.Key));
|
||||
}
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(keys.Result.PrivateKey))
|
||||
{
|
||||
_cryptoService.SetPrivateKey(new CipherString(keys.Result.PrivateKey));
|
||||
}
|
||||
if(!string.IsNullOrWhiteSpace(profile.PrivateKey))
|
||||
{
|
||||
_cryptoService.SetPrivateKey(new CipherString(profile.PrivateKey));
|
||||
}
|
||||
|
||||
_cryptoService.SetOrgKeys(profile);
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
private void SyncStarted()
|
||||
|
||||
Reference in New Issue
Block a user