mirror of
https://github.com/bitwarden/mobile
synced 2025-12-19 17:53:47 +00:00
async vault fetch and filter (search) tasks. Resolved singleton crypto issue around reuse of PaddedBufferedBlockCipher
This commit is contained in:
@@ -48,6 +48,7 @@ namespace Bit.App.Pages
|
|||||||
public ListView ListView { get; set; }
|
public ListView ListView { get; set; }
|
||||||
public IEnumerable<VaultListPageModel.Site> Sites { get; set; } = new List<VaultListPageModel.Site>();
|
public IEnumerable<VaultListPageModel.Site> Sites { get; set; } = new List<VaultListPageModel.Site>();
|
||||||
public IEnumerable<VaultListPageModel.Folder> Folders { get; set; } = new List<VaultListPageModel.Folder>();
|
public IEnumerable<VaultListPageModel.Folder> Folders { get; set; } = new List<VaultListPageModel.Folder>();
|
||||||
|
public SearchBar Search { get; set; }
|
||||||
|
|
||||||
private void Init()
|
private void Init()
|
||||||
{
|
{
|
||||||
@@ -77,18 +78,18 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
ListView.ItemSelected += SiteSelected;
|
ListView.ItemSelected += SiteSelected;
|
||||||
|
|
||||||
var searchBar = new SearchBar
|
Search = new SearchBar
|
||||||
{
|
{
|
||||||
Placeholder = "Search vault...",
|
Placeholder = "Search vault...",
|
||||||
BackgroundColor = Color.FromHex("efeff4")
|
BackgroundColor = Color.FromHex("efeff4")
|
||||||
};
|
};
|
||||||
searchBar.TextChanged += SearchBar_TextChanged;
|
Search.TextChanged += SearchBar_TextChanged;
|
||||||
searchBar.SearchButtonPressed += SearchBar_SearchButtonPressed;
|
Search.SearchButtonPressed += SearchBar_SearchButtonPressed;
|
||||||
|
|
||||||
Title = _favorites ? AppResources.Favorites : AppResources.MyVault;
|
Title = _favorites ? AppResources.Favorites : AppResources.MyVault;
|
||||||
Content = new StackLayout
|
Content = new StackLayout
|
||||||
{
|
{
|
||||||
Children = { searchBar, ListView },
|
Children = { Search, ListView },
|
||||||
Spacing = 0
|
Spacing = 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -112,16 +113,25 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
private void FilterResults(string searchFilter)
|
private void FilterResults(string searchFilter)
|
||||||
{
|
{
|
||||||
if(string.IsNullOrWhiteSpace(searchFilter))
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
LoadFolders(Sites);
|
await Task.Delay(300);
|
||||||
}
|
if(searchFilter != Search.Text)
|
||||||
else
|
{
|
||||||
{
|
return;
|
||||||
searchFilter = searchFilter.ToLower();
|
}
|
||||||
var filteredSites = Sites.Where(s => s.Name.ToLower().Contains(searchFilter) || s.Username.ToLower().Contains(searchFilter));
|
|
||||||
LoadFolders(filteredSites);
|
if(string.IsNullOrWhiteSpace(searchFilter))
|
||||||
}
|
{
|
||||||
|
LoadFolders(Sites);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
searchFilter = searchFilter.ToLower();
|
||||||
|
var filteredSites = Sites.Where(s => s.Name.ToLower().Contains(searchFilter) || s.Username.ToLower().Contains(searchFilter));
|
||||||
|
LoadFolders(filteredSites);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async override void OnAppearing()
|
protected async override void OnAppearing()
|
||||||
@@ -151,17 +161,20 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
private async Task FetchAndLoadVaultAsync()
|
private async Task FetchAndLoadVaultAsync()
|
||||||
{
|
{
|
||||||
var foldersTask = _folderService.GetAllAsync();
|
await Task.Run(async () =>
|
||||||
var sitesTask = _favorites ? _siteService.GetAllAsync(true) : _siteService.GetAllAsync();
|
{
|
||||||
await Task.WhenAll(foldersTask, sitesTask);
|
var foldersTask = _folderService.GetAllAsync();
|
||||||
|
var sitesTask = _favorites ? _siteService.GetAllAsync(true) : _siteService.GetAllAsync();
|
||||||
|
await Task.WhenAll(foldersTask, sitesTask);
|
||||||
|
|
||||||
var folders = await foldersTask;
|
var folders = await foldersTask;
|
||||||
var sites = await sitesTask;
|
var sites = await sitesTask;
|
||||||
|
|
||||||
Folders = folders.Select(f => new VaultListPageModel.Folder(f));
|
Folders = folders.Select(f => new VaultListPageModel.Folder(f));
|
||||||
Sites = sites.Select(s => new VaultListPageModel.Site(s));
|
Sites = sites.Select(s => new VaultListPageModel.Site(s));
|
||||||
|
|
||||||
LoadFolders(Sites);
|
LoadFolders(Sites);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadFolders(IEnumerable<VaultListPageModel.Site> sites)
|
private void LoadFolders(IEnumerable<VaultListPageModel.Site> sites)
|
||||||
|
|||||||
@@ -21,16 +21,13 @@ namespace Bit.App.Services
|
|||||||
private const int Iterations = 5000;
|
private const int Iterations = 5000;
|
||||||
|
|
||||||
private readonly Random _random = new Random();
|
private readonly Random _random = new Random();
|
||||||
private readonly PaddedBufferedBlockCipher _cipher;
|
|
||||||
private readonly ISecureStorageService _secureStorage;
|
private readonly ISecureStorageService _secureStorage;
|
||||||
|
private readonly CbcBlockCipher _aesBlockCipher;
|
||||||
private KeyParameter _keyParameter;
|
private KeyParameter _keyParameter;
|
||||||
|
|
||||||
public CryptoService(ISecureStorageService secureStorage)
|
public CryptoService(ISecureStorageService secureStorage)
|
||||||
{
|
{
|
||||||
var engine = new AesEngine();
|
_aesBlockCipher = new CbcBlockCipher(new AesEngine());
|
||||||
var blockCipher = new CbcBlockCipher(engine);
|
|
||||||
_cipher = new PaddedBufferedBlockCipher(blockCipher);
|
|
||||||
|
|
||||||
_secureStorage = secureStorage;
|
_secureStorage = secureStorage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,10 +93,11 @@ namespace Bit.App.Services
|
|||||||
var iv = GenerateRandomInitializationVector();
|
var iv = GenerateRandomInitializationVector();
|
||||||
var keyParamWithIV = new ParametersWithIV(_keyParameter, iv, 0, InitializationVectorSize);
|
var keyParamWithIV = new ParametersWithIV(_keyParameter, iv, 0, InitializationVectorSize);
|
||||||
|
|
||||||
_cipher.Init(true, keyParamWithIV);
|
var cipher = new PaddedBufferedBlockCipher(_aesBlockCipher);
|
||||||
var encryptedBytes = new byte[_cipher.GetOutputSize(plaintextBytes.Length)];
|
cipher.Init(true, keyParamWithIV);
|
||||||
var length = _cipher.ProcessBytes(plaintextBytes, encryptedBytes, 0);
|
var encryptedBytes = new byte[cipher.GetOutputSize(plaintextBytes.Length)];
|
||||||
_cipher.DoFinal(encryptedBytes, length);
|
var length = cipher.ProcessBytes(plaintextBytes, encryptedBytes, 0);
|
||||||
|
cipher.DoFinal(encryptedBytes, length);
|
||||||
|
|
||||||
return new CipherString(Convert.ToBase64String(iv), Convert.ToBase64String(encryptedBytes));
|
return new CipherString(Convert.ToBase64String(iv), Convert.ToBase64String(encryptedBytes));
|
||||||
}
|
}
|
||||||
@@ -119,10 +117,11 @@ namespace Bit.App.Services
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var keyParamWithIV = new ParametersWithIV(_keyParameter, encyptedValue.InitializationVectorBytes, 0, InitializationVectorSize);
|
var keyParamWithIV = new ParametersWithIV(_keyParameter, encyptedValue.InitializationVectorBytes, 0, InitializationVectorSize);
|
||||||
_cipher.Init(false, keyParamWithIV);
|
var cipher = new PaddedBufferedBlockCipher(_aesBlockCipher);
|
||||||
byte[] comparisonBytes = new byte[_cipher.GetOutputSize(encyptedValue.CipherTextBytes.Length)];
|
cipher.Init(false, keyParamWithIV);
|
||||||
var length = _cipher.ProcessBytes(encyptedValue.CipherTextBytes, comparisonBytes, 0);
|
byte[] comparisonBytes = new byte[cipher.GetOutputSize(encyptedValue.CipherTextBytes.Length)];
|
||||||
_cipher.DoFinal(comparisonBytes, length);
|
var length = cipher.ProcessBytes(encyptedValue.CipherTextBytes, comparisonBytes, 0);
|
||||||
|
cipher.DoFinal(comparisonBytes, length);
|
||||||
return Encoding.UTF8.GetString(comparisonBytes, 0, comparisonBytes.Length).TrimEnd('\0');
|
return Encoding.UTF8.GetString(comparisonBytes, 0, comparisonBytes.Length).TrimEnd('\0');
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
|
|||||||
Reference in New Issue
Block a user