예제 #1
0
        /// <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;
            }
        }
예제 #2
0
        /// <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;
            }
        }
예제 #3
0
        /// <summary>
        /// Creates a new <see cref="Fortress"/> with a <see cref="MasterKey"/> and saves it encrypted.
        /// </summary>
        internal void WriteFortress(Fortress fortress, bool overwrite = false)
        {
            try
            {
                Logger.log.Info("Starting to write a fortress...");
                var databasePath = Path.Combine(fortress.FullPath, TermHelper.GetDatabaseTerm());

                // =========================================================== Create the root directory

                IOPathHelper.CreateDirectory(fortress.FullPath);
                Logger.log.Debug($"Created outer walls {fortress.FullPath}.");

                // =========================================================== Create the sub directories for the database

                IOPathHelper.CreateDirectory(databasePath);
                Logger.log.Debug($"Created the {TermHelper.GetDatabaseTerm()}");

                // =========================================================== Create the file which holds the salt to unlock the database

                StoreSalt(fortress.FullPath, fortress.Salt);
                Logger.log.Debug("Stored salt");

                // =========================================================== Store the user Input and initial data in the database

                foreach (var modelList in _unsecureDatacache.Values) // UnsecureDatacache
                {
                    foreach (var model in modelList)
                    {
                        StoreOne(model);
                    }
                }

                foreach (var pair in _secureDatacache)
                {
                    // We filter: Only if the sensible data has a parent we want to save it. Otherwise the parent has been deleted,
                    // which makes the sensible counterpart useless.
                    if (_unsecureDatacache.Values.Any(l => l.Any(m => m.Id == pair.Key)))
                    {
                        var byteModel = new ByteModel(pair.Key, pair.Value);
                        StoreOne(null, true, byteModel);
                    }
                }

                Logger.log.Debug("Stored fortress information.");

                // =========================================================== Zip only the database

                ZipHelper.ZipSavedArchives(databasePath, $"{databasePath}{TermHelper.GetZippedFileEnding()}");
                Directory.Delete(databasePath, true);
                Logger.log.Debug($"{TermHelper.GetDatabaseTerm()} has been zipped.");

                // =========================================================== Encrypt the database

                var aesAlg = new AesAlgorithm();
                // Read all bytes from the database directory
                var data = File.ReadAllBytes($"{databasePath}{TermHelper.GetZippedFileEnding()}");
                // Encrypt it
                var encryptedData = aesAlg.Encrypt(data, fortress.MasterKey.Value, fortress.Salt);
                // Write the encrypted file
                File.WriteAllBytes($"{databasePath}{TermHelper.GetDatabaseEnding()}", encryptedData);
                // Delete the zip
                File.Delete($"{databasePath}{TermHelper.GetZippedFileEnding()}");
                Logger.log.Debug($"Encrypted {TermHelper.GetDatabaseTerm()}");

                // =========================================================== Zip the whole fortress

                if (overwrite)
                {
                    File.Delete($"{fortress.FullPath}{TermHelper.GetZippedFileEnding()}");
                }

                ZipHelper.ZipSavedArchives(fortress.FullPath, $"{fortress.FullPath}{TermHelper.GetZippedFileEnding()}");
                Directory.Delete(fortress.FullPath, true);
                Logger.log.Debug("Fortress has been zipped.");

                Logger.log.Info("Fortress has been sucessfully written!");
            }
            catch (Exception ex)
            {
                // Delete all changes that have been made to this point. We do not want half-built fortresses.
                if (Directory.Exists(fortress.FullPath))
                {
                    Directory.Delete(fortress.FullPath, true);
                }
                if (File.Exists(Path.Combine(fortress.FullPath, TermHelper.GetZippedFileEnding())))
                {
                    File.Delete(fortress.FullPath + TermHelper.GetZippedFileEnding());
                }

                ex.SetUserMessage(WellKnownExceptionMessages.DataExceptionMessage());
                throw ex;
            }
        }