async vault fetch and filter (search) tasks. Resolved singleton crypto issue around reuse of PaddedBufferedBlockCipher

This commit is contained in:
Kyle Spearrin 2016-07-11 19:36:39 -04:00
parent f9fd53c733
commit f0455aad74
2 changed files with 46 additions and 34 deletions

View file

@ -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)

View file

@ -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)