private async void Save_Button_Click(object sender, RoutedEventArgs e) { try { await Task.Run(() => { Application.Current.Dispatcher.Invoke(() => InformationPanel_Textblock.Text = "Validating your rights..."); // Validate the key first. if (DataAccessService.Instance.ValidateMasterkey(masterPasswordBox.Password)) { var aesHelper = new AesHelper(); var hashedKey = aesHelper.CreateKey(masterPasswordBox.Password, 256, CurrentFortressData.Salt); var secureMasterkey = new Masterkey(hashedKey); hashedKey = null; Application.Current.Dispatcher.Invoke(() => InformationPanel_Textblock.Text = "You have the correct keys my friend."); IOPathHelper.CreateDirectory(IOPathHelper.GetBackedUpFortressDirectory()); // Make sure the directory exists. // Backup fortress Application.Current.Dispatcher.Invoke(() => InformationPanel_Textblock.Text = "Backup-ing your fortress..."); DataAccessService.Instance.BackupFortress( System.IO.Path.Combine(IOPathHelper.GetBackedUpFortressDirectory(), $"(Backup){CurrentFortressData.FortressName}{TermHelper.GetZippedFileEnding()}")); Application.Current.Dispatcher.Invoke(() => InformationPanel_Textblock.Text = "Fortress backed up. Proceeding to save the fortress..."); // Now save the fortress. DataAccessService.Instance.SaveFortress(secureMasterkey); Application.Current.Dispatcher.Invoke(() => InformationPanel_Textblock.Text = "Fortress saved successfully."); // Backup the fortress again with the newly saved changes. DataAccessService.Instance.BackupFortress( System.IO.Path.Combine(IOPathHelper.GetBackedUpFortressDirectory(), $"(Backup){CurrentFortressData.FortressName}{TermHelper.GetZippedFileEnding()}")); Thread.Sleep(1000); // Make the user see the result for a second. Application.Current.Dispatcher.Invoke(() => DialogResult = true); } else { Application.Current.Dispatcher.Invoke(() => InformationPanel_Textblock.Text = "The mission could not be executed."); return; } }); } catch (Exception ex) { Logger.log.Error(ex); InformationPanel_Textblock.Text = "The mission could not be executed."; return; } finally { masterPasswordBox.Password = string.Empty; // Delete the password } }
/// <summary> /// Validates the masterkey by decrypting the given fortress and flushing the memory afterwards. /// </summary> /// <param name="fortressFullPath"></param> /// <param name="fortressName"></param> /// <param name="password"></param> internal void ValidateMasterKey(string fortressFullPath, string fortressName, string password) { try { Logger.log.Info($"Start validating the masterkey of fortress {fortressFullPath}..."); var aesHelper = new AesHelper(); // =========================================================== Unzip the fortress - Read salt var unzippedFortress = ZipHelper.UnzipSavedZip(fortressFullPath); using (unzippedFortress) { var entryOfSalt = fortressName + "/salt" + TermHelper.GetTextFileEnding(); var saltEntry = unzippedFortress.GetEntry(entryOfSalt); var saltBytes = new byte[32]; using (var stream = saltEntry.Open()) { saltBytes = ByteHelper.ReadBytesOfStream(stream); } Logger.log.Debug("Unzipped fortress - Salt bytes read."); // =========================================================== Create masterkey var hashedKey = aesHelper.CreateKey(password, 256, saltBytes); password = string.Empty; // Delete the password in plaintext from RAM var masterKey = new Masterkey(hashedKey); Logger.log.Debug("Masterkey created."); // =========================================================== Decrypt database var entryOfDatabase = fortressName + "/" + TermHelper.GetDatabaseTerm() + TermHelper.GetDatabaseEnding(); var databaseEntry = unzippedFortress.GetEntry(entryOfDatabase); var aesAlg = new AesAlgorithm(); using (var stream = databaseEntry.Open()) { var dbBytes = ByteHelper.ReadBytesOfStream(stream); var decryptedDb = aesAlg.Decrypt(dbBytes, masterKey.Value, saltBytes); Logger.log.Info($"Validated {TermHelper.GetDatabaseTerm()}"); decryptedDb = null; } } } catch (Exception ex) { ex.SetUserMessage(WellKnownExceptionMessages.DataExceptionMessage()); throw ex; } }
/// <summary> /// Opens a <see cref="Fortress"/> and loads the database. /// </summary> public void BuildFortress(string fortressFullPath, string fortressName, string password) { try { Logger.log.Info($"Start opening the fortress {fortressFullPath}..."); var aesHelper = new AesHelper(); // =========================================================== Unzip the fortress - Read salt var unzippedFortress = ZipHelper.UnzipSavedZip(fortressFullPath); using (unzippedFortress) { var entryOfSalt = fortressName + "/salt" + TermHelper.GetTextFileEnding(); var saltEntry = unzippedFortress.GetEntry(entryOfSalt); var saltBytes = new byte[32]; using (var stream = saltEntry.Open()) { saltBytes = ByteHelper.ReadBytesOfStream(stream); } CurrentFortressData.Salt = saltBytes; Logger.log.Debug("Unzipped fortress - Salt bytes read."); // =========================================================== Create masterkey var hashedKey = aesHelper.CreateKey(password, 256, saltBytes); password = string.Empty; // Delete the password in plaintext from RAM var masterKey = new Masterkey(hashedKey); hashedKey = null; // Hash also Logger.log.Debug("Masterkey created."); // =========================================================== Decrypt database var entryOfDatabase = fortressName + "/" + TermHelper.GetDatabaseTerm() + TermHelper.GetDatabaseEnding(); var databaseEntry = unzippedFortress.GetEntry(entryOfDatabase); var aesAlg = new AesAlgorithm(); using (var stream = databaseEntry.Open()) { var dbBytes = ByteHelper.ReadBytesOfStream(stream); var decryptedDb = aesAlg.Decrypt(dbBytes, masterKey.Value, saltBytes); Logger.log.Info($"Decrypted {TermHelper.GetDatabaseTerm()}"); // =========================================================== Unzip database // We distinguish between sensible data and normal data. We put the sensible data into the secureDatacache. var unzippedByteEntriesOfDb = ZipHelper.GetEntriesFromZipArchive(decryptedDb); // These are the entries in byte arrays decryptedDb = null; // Add to secureDC. foreach (var sensibleBytes in unzippedByteEntriesOfDb.Item2.Item2.ToList()) // ToList() otherwise the iterations throws exception { AddToSecureMemoryDC(unzippedByteEntriesOfDb.Item2.Item1.Pop(), unzippedByteEntriesOfDb.Item2.Item2.Pop()); } foreach (var bytes in unzippedByteEntriesOfDb.Item1.ToList()) // Add not sensible data to the "unsecure" DC. { AddToUnsecureMemoryDC(BuildModelsOutOfBytes <ModelBase>(unzippedByteEntriesOfDb.Item1.Pop())); } unzippedByteEntriesOfDb = null; } // Track the security parameters for scans later. SecurityParameterProvider.Instance.UpdateHash(nameof(Fortress), fortressFullPath); } } catch (Exception ex) { ex.SetUserMessage(WellKnownExceptionMessages.DataExceptionMessage()); throw ex; } }
private void Register_Button_Click(object sender, RoutedEventArgs e) { try { Reset(); var currentPw = string.Empty; var currentReenteredPw = string.Empty; if (_pwIsVisible) { currentPw = Master_VisibleTextbox.Text; currentReenteredPw = MasterReentered_Textbox.Text; } else { currentPw = Master_PasswordBox.Password; currentReenteredPw = MasterReentered_PasswordBox.Password; } // Check if all criteria are correct if (Info_Checkbox.IsChecked == false) { Output_Textblock.Text = "You need to varify first that you have read the text on the left."; Info_Checkbox.Foreground = Brushes.Red; return; } if (FortressName_Textbox.Text == string.Empty) { Output_Textblock.Text = "You need to name your fortress."; FortressName_Textbox.BorderBrush = Brushes.Red; return; } if (WellKnownSpecialCharacters.ContainsSpecialCharacters(FortressName_Textbox.Text)) { Output_Textblock.Text = "Special characters in the name are not allowed."; FortressName_Textbox.BorderBrush = Brushes.Red; return; } if (currentPw.Length < 8 || !(currentPw.Any(char.IsUpper)) || !(currentPw.Any(char.IsDigit))) { Output_Textblock.Text = "The masterkey has to match the following criteria: Minumum 8 characters long; Contain at least one upper case character and one digit."; Master_PasswordBox.Foreground = Brushes.Red; Master_VisibleTextbox.Foreground = Brushes.Red; return; } if (currentReenteredPw != currentPw) { Output_Textblock.Text = "Masterkey doesn't match the reentered one."; MasterReentered_PasswordBox.Foreground = Brushes.Red; MasterReentered_Textbox.Foreground = Brushes.Red; return; } // If they are - continue to make the fortress. var aesHelper = new AesHelper(); var salt = aesHelper.GenerateSalt(); var hashedKey = aesHelper.CreateKey(Master_PasswordBox.Password, 256, salt); var fullPath = string.Empty; // If the user has entered a custom path -> Disabled for now if (_fullPath != string.Empty) { fullPath = $"{_fullPath}\\{FortressName_Textbox.Text}"; } else // else use the default. { fullPath = $"{IOPathHelper.GetDefaultFortressDirectory()}\\{FortressName_Textbox.Text}"; } var name = "NOT GIVEN"; var lastName = "NOT GIVEN"; var userName = "******"; var eMail = "*****@*****.**"; var fortress = new Fortress(salt, hashedKey, fullPath, name, lastName, userName, eMail); DataAccessService.Instance.CreateNewFortress(fortress); // Create the new fortress. ClearPasswords(); Navigation.LoginManagementInstance.LoadFortresses(); // Refresh the list. Communication.InformUser($"{FortressName_Textbox.Text} has been successfully built."); } catch (Exception ex) { ClearPasswords(); Logger.log.Error($"Error while trying to register a new fortress: {ex}"); ex.SetUserMessage("There was a problem creating the fortress. The given passwords have been flushed out of memory."); Communication.InformUserAboutError(ex); } }