/// <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> /// Do NOT use this unless a salt is stored in a single file. /// </summary> internal void StoreSalt(string path, byte[] salt) { CheckDatacache(); File.WriteAllBytes(Path.Combine(path, $"salt{TermHelper.GetTextFileEnding()}"), salt); }
/// <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; } }