From 5016c14ff38eeac6b48dafe2986a2b2a7eca231b Mon Sep 17 00:00:00 2001 From: dbuechel Date: Fri, 22 Feb 2019 10:02:34 +0100 Subject: [PATCH] SEBWIN-296: Implemented unit tests for configuration repository. --- .../ConfigurationRepositoryTests.cs | 261 +++++++++++++++++- .../ConfigurationData/CertificateImporter.cs | 76 ----- .../ConfigurationRepository.cs | 7 +- .../Cryptography/CertificateStore.cs | 62 +++++ .../SafeExamBrowser.Configuration.csproj | 1 - .../Cryptography/ICertificateStore.cs | 8 +- SafeExamBrowser.Runtime/CompositionRoot.cs | 8 +- 7 files changed, 333 insertions(+), 90 deletions(-) delete mode 100644 SafeExamBrowser.Configuration/ConfigurationData/CertificateImporter.cs diff --git a/SafeExamBrowser.Configuration.UnitTests/ConfigurationRepositoryTests.cs b/SafeExamBrowser.Configuration.UnitTests/ConfigurationRepositoryTests.cs index 81986b0c..6e5a483d 100644 --- a/SafeExamBrowser.Configuration.UnitTests/ConfigurationRepositoryTests.cs +++ b/SafeExamBrowser.Configuration.UnitTests/ConfigurationRepositoryTests.cs @@ -7,11 +7,16 @@ */ using System; +using System.Collections.Generic; +using System.IO; using System.Reflection; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; +using SafeExamBrowser.Configuration.ConfigurationData; using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration.Cryptography; +using SafeExamBrowser.Contracts.Configuration.DataFormats; +using SafeExamBrowser.Contracts.Configuration.DataResources; using SafeExamBrowser.Contracts.Logging; namespace SafeExamBrowser.Configuration.UnitTests @@ -20,19 +25,252 @@ namespace SafeExamBrowser.Configuration.UnitTests public class ConfigurationRepositoryTests { private ConfigurationRepository sut; + private Mock binaryParser; + private Mock binarySerializer; + private Mock certificateStore; + private Mock fileLoader; + private Mock fileSaver; + private Mock hashAlgorithm; + private Mock logger; + private Mock networkLoader; + private Mock xmlParser; + private Mock xmlSerializer; [TestInitialize] public void Initialize() { var executablePath = Assembly.GetExecutingAssembly().Location; - var hashAlgorithm = new Mock(); - var logger = new Mock(); - sut = new ConfigurationRepository(hashAlgorithm.Object, logger.Object, executablePath, string.Empty, string.Empty, string.Empty); + binaryParser = new Mock(); + binarySerializer = new Mock(); + certificateStore = new Mock(); + fileLoader = new Mock(); + fileSaver = new Mock(); + hashAlgorithm = new Mock(); + logger = new Mock(); + networkLoader = new Mock(); + xmlParser = new Mock(); + xmlSerializer = new Mock(); + + fileLoader.Setup(f => f.CanLoad(It.IsAny())).Returns(u => u.IsFile); + fileSaver.Setup(f => f.CanSave(It.IsAny())).Returns(u => u.IsFile); + networkLoader.Setup(n => n.CanLoad(It.IsAny())).Returns(u => u.Scheme.Equals("http") || u.Scheme.Equals("seb")); + + sut = new ConfigurationRepository(certificateStore.Object, hashAlgorithm.Object, logger.Object, executablePath, string.Empty, string.Empty, string.Empty); + sut.InitializeAppConfig(); } [TestMethod] - public void MustCorrectlyInitializeSessionConfiguration() + public void ConfigureClient_MustWorkAsExpected() + { + var stream = new MemoryStream() as Stream; + var password = new PasswordParameters { Password = "test123" }; + var parseResult = new ParseResult + { + Format = FormatType.Binary, + RawData = new Dictionary(), + Status = LoadStatus.Success + }; + var serializeResult = new SerializeResult + { + Data = new MemoryStream(), + Status = SaveStatus.Success + }; + + RegisterModules(); + + fileLoader.Setup(n => n.TryLoad(It.IsAny(), out stream)).Returns(LoadStatus.Success); + binaryParser.Setup(b => b.CanParse(It.IsAny())).Returns(true); + binaryParser.Setup(b => b.TryParse(It.IsAny(), It.IsAny())).Returns(parseResult); + binarySerializer.Setup(b => b.CanSerialize(FormatType.Binary)).Returns(true); + binarySerializer.Setup(b => b.TrySerialize(It.IsAny>(), It.IsAny())).Returns(serializeResult); + fileSaver.Setup(f => f.TrySave(It.IsAny(), It.IsAny())).Returns(SaveStatus.Success); + + var status = sut.ConfigureClientWith(new Uri("C:\\TEMP\\Some\\file.seb"), password); + + fileLoader.Verify(n => n.TryLoad(It.IsAny(), out stream), Times.Once); + binaryParser.Verify(b => b.TryParse(It.IsAny(), It.IsAny()), Times.Once); + certificateStore.Verify(c => c.ExtractAndImportIdentities(It.IsAny>()), Times.Once); + binarySerializer.Verify(b => b.TrySerialize( + It.IsAny>(), + It.Is(p => p.IsHash == true && p.Password == string.Empty)), Times.Once); + fileSaver.Verify(f => f.TrySave(It.IsAny(), It.IsAny()), Times.Once); + + Assert.AreEqual(SaveStatus.Success, status); + } + + [TestMethod] + public void ConfigureClient_MustKeepSameEncryptionAccordingToConfiguration() + { + var stream = new MemoryStream() as Stream; + var password = new PasswordParameters { Password = "test123" }; + var parseResult = new ParseResult + { + Encryption = new PublicKeyParameters + { + InnerEncryption = password, + SymmetricEncryption = true + }, + Format = FormatType.Binary, + RawData = new Dictionary { { Keys.ConfigurationFile.KeepClientConfigEncryption, true } }, + Status = LoadStatus.Success + }; + var serializeResult = new SerializeResult + { + Data = new MemoryStream(), + Status = SaveStatus.Success + }; + + RegisterModules(); + + fileLoader.Setup(n => n.TryLoad(It.IsAny(), out stream)).Returns(LoadStatus.Success); + binaryParser.Setup(b => b.CanParse(It.IsAny())).Returns(true); + binaryParser.Setup(b => b.TryParse(It.IsAny(), It.IsAny())).Returns(parseResult); + binarySerializer.Setup(b => b.CanSerialize(FormatType.Binary)).Returns(true); + binarySerializer.Setup(b => b.TrySerialize(It.IsAny>(), It.IsAny())).Returns(serializeResult); + fileSaver.Setup(f => f.TrySave(It.IsAny(), It.IsAny())).Returns(SaveStatus.Success); + + var status = sut.ConfigureClientWith(new Uri("C:\\TEMP\\Some\\file.seb"), password); + + binarySerializer.Verify(b => b.TrySerialize( + It.IsAny>(), + It.Is(p => p.InnerEncryption == password && p.SymmetricEncryption)), Times.Once); + + Assert.AreEqual(SaveStatus.Success, status); + } + + [TestMethod] + public void ConfigureClient_MustAbortProcessOnError() + { + var stream = new MemoryStream() as Stream; + var password = new PasswordParameters { Password = "test123" }; + var parseResult = new ParseResult + { + Format = FormatType.Binary, + RawData = new Dictionary(), + Status = LoadStatus.Success + }; + var serializeResult = new SerializeResult + { + Data = new MemoryStream(), + Status = SaveStatus.Success + }; + + RegisterModules(); + + fileLoader.Setup(n => n.TryLoad(It.IsAny(), out stream)).Returns(LoadStatus.Success); + binaryParser.Setup(b => b.CanParse(It.IsAny())).Throws(); + + var status = sut.ConfigureClientWith(new Uri("C:\\TEMP\\Some\\file.seb"), password); + + fileLoader.Verify(n => n.TryLoad(It.IsAny(), out stream), Times.Once); + binaryParser.Verify(b => b.TryParse(It.IsAny(), It.IsAny()), Times.Never); + certificateStore.Verify(c => c.ExtractAndImportIdentities(It.IsAny>()), Times.Never); + binarySerializer.Verify(b => b.TrySerialize(It.IsAny>(), It.IsAny()), Times.Never); + fileSaver.Verify(f => f.TrySave(It.IsAny(), It.IsAny()), Times.Never); + + Assert.AreEqual(SaveStatus.UnexpectedError, status); + } + + [TestMethod] + public void TryLoad_MustWorkAsExpected() + { + var stream = new MemoryStream() as Stream; + var parseResult = new ParseResult { RawData = new Dictionary(), Status = LoadStatus.Success }; + + RegisterModules(); + + networkLoader.Setup(n => n.TryLoad(It.IsAny(), out stream)).Returns(LoadStatus.Success); + binaryParser.Setup(b => b.CanParse(It.IsAny())).Returns(true); + binaryParser.Setup(b => b.TryParse(It.IsAny(), It.IsAny())).Returns(parseResult); + + var result = sut.TryLoadSettings(new Uri("http://www.blubb.org"), out _); + + fileLoader.Verify(f => f.CanLoad(It.IsAny()), Times.Once); + fileLoader.Verify(f => f.TryLoad(It.IsAny(), out stream), Times.Never); + networkLoader.Verify(n => n.CanLoad(It.IsAny()), Times.Once); + networkLoader.Verify(n => n.TryLoad(It.IsAny(), out stream), Times.Once); + binaryParser.Verify(b => b.CanParse(It.IsAny()), Times.Once); + binaryParser.Verify(b => b.TryParse(It.IsAny(), It.IsAny()), Times.Once); + xmlParser.Verify(x => x.CanParse(It.IsAny()), Times.AtMostOnce); + xmlParser.Verify(x => x.TryParse(It.IsAny(), It.IsAny()), Times.Never); + + Assert.AreEqual(LoadStatus.Success, result); + } + + [TestMethod] + public void TryLoad_MustReportPasswordNeed() + { + var stream = new MemoryStream() as Stream; + var parseResult = new ParseResult { Status = LoadStatus.PasswordNeeded }; + + RegisterModules(); + + networkLoader.Setup(n => n.TryLoad(It.IsAny(), out stream)).Returns(LoadStatus.Success); + binaryParser.Setup(b => b.CanParse(It.IsAny())).Returns(true); + binaryParser.Setup(b => b.TryParse(It.IsAny(), It.IsAny())).Returns(parseResult); + + var result = sut.TryLoadSettings(new Uri("http://www.blubb.org"), out _); + + Assert.AreEqual(LoadStatus.PasswordNeeded, result); + } + + [TestMethod] + public void TryLoad_MustNotFailToIfNoLoaderRegistered() + { + var result = sut.TryLoadSettings(new Uri("http://www.blubb.org"), out _); + + Assert.AreEqual(LoadStatus.NotSupported, result); + + sut.Register(fileLoader.Object); + sut.Register(networkLoader.Object); + + result = sut.TryLoadSettings(new Uri("ftp://www.blubb.org"), out _); + + fileLoader.Verify(f => f.CanLoad(It.IsAny()), Times.Once); + networkLoader.Verify(n => n.CanLoad(It.IsAny()), Times.Once); + + Assert.AreEqual(LoadStatus.NotSupported, result); + } + + [TestMethod] + public void TryLoad_MustNotFailIfNoParserRegistered() + { + var data = default(Stream); + + networkLoader.Setup(l => l.TryLoad(It.IsAny(), out data)).Returns(LoadStatus.Success); + sut.Register(networkLoader.Object); + + var result = sut.TryLoadSettings(new Uri("http://www.blubb.org"), out _); + + networkLoader.Verify(n => n.TryLoad(It.IsAny(), out data), Times.Once); + + Assert.AreEqual(LoadStatus.NotSupported, result); + } + + [TestMethod] + public void TryLoad_MustNotFailInCaseOfUnexpectedError() + { + var data = default(Stream); + + networkLoader.Setup(l => l.TryLoad(It.IsAny(), out data)).Throws(); + sut.Register(networkLoader.Object); + + var result = sut.TryLoadSettings(new Uri("http://www.blubb.org"), out _); + + Assert.AreEqual(LoadStatus.UnexpectedError, result); + + binaryParser.Setup(b => b.CanParse(It.IsAny())).Throws(); + networkLoader.Setup(l => l.TryLoad(It.IsAny(), out data)).Returns(LoadStatus.Success); + sut.Register(binaryParser.Object); + + result = sut.TryLoadSettings(new Uri("http://www.blubb.org"), out _); + + Assert.AreEqual(LoadStatus.UnexpectedError, result); + } + + [TestMethod] + public void MustInitializeSessionConfiguration() { var appConfig = sut.InitializeAppConfig(); var configuration = sut.InitializeSessionConfiguration(); @@ -44,7 +282,7 @@ namespace SafeExamBrowser.Configuration.UnitTests } [TestMethod] - public void MustCorrectlyUpdateAppConfig() + public void MustUpdateAppConfig() { var appConfig = sut.InitializeAppConfig(); var clientAddress = appConfig.ClientAddress; @@ -64,7 +302,7 @@ namespace SafeExamBrowser.Configuration.UnitTests } [TestMethod] - public void MustCorrectlyUpdateSessionConfiguration() + public void MustUpdateSessionConfiguration() { var appConfig = sut.InitializeAppConfig(); var firstSession = sut.InitializeSessionConfiguration(); @@ -76,5 +314,16 @@ namespace SafeExamBrowser.Configuration.UnitTests Assert.AreNotEqual(secondSession.Id, thirdSession.Id); Assert.AreNotEqual(secondSession.StartupToken, thirdSession.StartupToken); } + + private void RegisterModules() + { + sut.Register(binaryParser.Object); + sut.Register(binarySerializer.Object); + sut.Register(fileLoader.Object); + sut.Register(fileSaver.Object); + sut.Register(networkLoader.Object); + sut.Register(xmlParser.Object); + sut.Register(xmlSerializer.Object); + } } } diff --git a/SafeExamBrowser.Configuration/ConfigurationData/CertificateImporter.cs b/SafeExamBrowser.Configuration/ConfigurationData/CertificateImporter.cs deleted file mode 100644 index ae949246..00000000 --- a/SafeExamBrowser.Configuration/ConfigurationData/CertificateImporter.cs +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET) - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Security.Cryptography.X509Certificates; -using SafeExamBrowser.Contracts.Logging; - -namespace SafeExamBrowser.Configuration.ConfigurationData -{ - internal class CertificateImporter - { - private ILogger logger; - - internal CertificateImporter(ILogger logger) - { - this.logger = logger; - } - - internal void ExtractAndImportIdentities(IDictionary data) - { - const int IDENTITY_CERTIFICATE = 1; - var hasCertificates = data.TryGetValue(Keys.Network.Certificates.EmbeddedCertificates, out var value); - - if (hasCertificates && value is IList> certificates) - { - var toRemove = new List>(); - - foreach (var certificate in certificates) - { - var hasData = certificate.TryGetValue(Keys.Network.Certificates.CertificateData, out var dataValue); - var hasType = certificate.TryGetValue(Keys.Network.Certificates.CertificateType, out var typeValue); - var isIdentity = typeValue is int type && type == IDENTITY_CERTIFICATE; - - if (hasData && hasType && isIdentity && dataValue is byte[] certificateData) - { - ImportIdentityCertificate(certificateData, new X509Store(StoreLocation.CurrentUser)); - ImportIdentityCertificate(certificateData, new X509Store(StoreName.TrustedPeople, StoreLocation.LocalMachine)); - - toRemove.Add(certificate); - } - } - - toRemove.ForEach(c => certificates.Remove(c)); - } - } - - internal void ImportIdentityCertificate(byte[] certificateData, X509Store store) - { - try - { - var certificate = new X509Certificate2(); - - certificate.Import(certificateData, "Di𝈭l𝈖Ch𝈒ah𝉇t𝈁a𝉈Hai1972", X509KeyStorageFlags.UserKeySet | X509KeyStorageFlags.PersistKeySet); - - store.Open(OpenFlags.ReadWrite); - store.Add(certificate); - - logger.Info($"Successfully imported identity certificate into {store.Location}.{store.Name}."); - } - catch (Exception e) - { - logger.Error($"Failed to import identity certificate into {store.Location}.{store.Name}!", e); - } - finally - { - store.Close(); - } - } - } -} diff --git a/SafeExamBrowser.Configuration/ConfigurationRepository.cs b/SafeExamBrowser.Configuration/ConfigurationRepository.cs index 550c4f38..137cc933 100644 --- a/SafeExamBrowser.Configuration/ConfigurationRepository.cs +++ b/SafeExamBrowser.Configuration/ConfigurationRepository.cs @@ -22,7 +22,7 @@ namespace SafeExamBrowser.Configuration { public class ConfigurationRepository : IConfigurationRepository { - private CertificateImporter certificateImporter; + private ICertificateStore certificateStore; private IList dataParsers; private IList dataSerializers; private DataMapper dataMapper; @@ -33,6 +33,7 @@ namespace SafeExamBrowser.Configuration private IList resourceSavers; public ConfigurationRepository( + ICertificateStore certificateStore, IHashAlgorithm hashAlgorithm, IModuleLogger logger, string executablePath, @@ -40,10 +41,10 @@ namespace SafeExamBrowser.Configuration string programTitle, string programVersion) { + this.certificateStore = certificateStore; this.hashAlgorithm = hashAlgorithm; this.logger = logger; - certificateImporter = new CertificateImporter(logger.CloneFor(nameof(CertificateImporter))); dataParsers = new List(); dataSerializers = new List(); dataMapper = new DataMapper(); @@ -64,7 +65,7 @@ namespace SafeExamBrowser.Configuration { TryParseData(data, out var encryption, out var format, out var rawData, password); - certificateImporter.ExtractAndImportIdentities(rawData); + certificateStore.ExtractAndImportIdentities(rawData); encryption = DetermineEncryptionForClientConfiguration(rawData, encryption); var status = TrySerializeData(rawData, format, out var serialized, encryption); diff --git a/SafeExamBrowser.Configuration/Cryptography/CertificateStore.cs b/SafeExamBrowser.Configuration/Cryptography/CertificateStore.cs index 52a7070e..d64ebd19 100644 --- a/SafeExamBrowser.Configuration/Cryptography/CertificateStore.cs +++ b/SafeExamBrowser.Configuration/Cryptography/CertificateStore.cs @@ -6,15 +6,21 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +using System; +using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; +using SafeExamBrowser.Configuration.ConfigurationData; using SafeExamBrowser.Contracts.Configuration.Cryptography; +using SafeExamBrowser.Contracts.Logging; namespace SafeExamBrowser.Configuration.Cryptography { public class CertificateStore : ICertificateStore { + private ILogger logger; + private readonly X509Store[] stores = new[] { new X509Store(StoreLocation.CurrentUser), @@ -22,6 +28,11 @@ namespace SafeExamBrowser.Configuration.Cryptography new X509Store(StoreName.TrustedPeople) }; + public CertificateStore(ILogger logger) + { + this.logger = logger; + } + public bool TryGetCertificateWith(byte[] keyHash, out X509Certificate2 certificate) { certificate = default(X509Certificate2); @@ -56,5 +67,56 @@ namespace SafeExamBrowser.Configuration.Cryptography return false; } + + public void ExtractAndImportIdentities(IDictionary data) + { + const int IDENTITY_CERTIFICATE = 1; + var hasCertificates = data.TryGetValue(Keys.Network.Certificates.EmbeddedCertificates, out var value); + + if (hasCertificates && value is IList> certificates) + { + var toRemove = new List>(); + + foreach (var certificate in certificates) + { + var hasData = certificate.TryGetValue(Keys.Network.Certificates.CertificateData, out var dataValue); + var hasType = certificate.TryGetValue(Keys.Network.Certificates.CertificateType, out var typeValue); + var isIdentity = typeValue is int type && type == IDENTITY_CERTIFICATE; + + if (hasData && hasType && isIdentity && dataValue is byte[] certificateData) + { + ImportIdentityCertificate(certificateData, new X509Store(StoreLocation.CurrentUser)); + ImportIdentityCertificate(certificateData, new X509Store(StoreName.TrustedPeople, StoreLocation.LocalMachine)); + + toRemove.Add(certificate); + } + } + + toRemove.ForEach(c => certificates.Remove(c)); + } + } + + private void ImportIdentityCertificate(byte[] certificateData, X509Store store) + { + try + { + var certificate = new X509Certificate2(); + + certificate.Import(certificateData, "Di𝈭l𝈖Ch𝈒ah𝉇t𝈁a𝉈Hai1972", X509KeyStorageFlags.UserKeySet | X509KeyStorageFlags.PersistKeySet); + + store.Open(OpenFlags.ReadWrite); + store.Add(certificate); + + logger.Info($"Successfully imported identity certificate into {store.Location}.{store.Name}."); + } + catch (Exception e) + { + logger.Error($"Failed to import identity certificate into {store.Location}.{store.Name}!", e); + } + finally + { + store.Close(); + } + } } } diff --git a/SafeExamBrowser.Configuration/SafeExamBrowser.Configuration.csproj b/SafeExamBrowser.Configuration/SafeExamBrowser.Configuration.csproj index f52d3191..638e8666 100644 --- a/SafeExamBrowser.Configuration/SafeExamBrowser.Configuration.csproj +++ b/SafeExamBrowser.Configuration/SafeExamBrowser.Configuration.csproj @@ -58,7 +58,6 @@ - diff --git a/SafeExamBrowser.Contracts/Configuration/Cryptography/ICertificateStore.cs b/SafeExamBrowser.Contracts/Configuration/Cryptography/ICertificateStore.cs index 220978fa..097ab20f 100644 --- a/SafeExamBrowser.Contracts/Configuration/Cryptography/ICertificateStore.cs +++ b/SafeExamBrowser.Contracts/Configuration/Cryptography/ICertificateStore.cs @@ -6,12 +6,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +using System.Collections.Generic; using System.Security.Cryptography.X509Certificates; namespace SafeExamBrowser.Contracts.Configuration.Cryptography { /// - /// Provides functionality to load certificates installed on the computer. + /// Provides functionality related to certificates installed on the computer. /// public interface ICertificateStore { @@ -20,5 +21,10 @@ namespace SafeExamBrowser.Contracts.Configuration.Cryptography /// Returns true if the certificate was found, otherwise false. /// bool TryGetCertificateWith(byte[] keyHash, out X509Certificate2 certificate); + + /// + /// Extracts all identity certificates from the given configuration data and installs them on the computer. + /// + void ExtractAndImportIdentities(IDictionary data); } } diff --git a/SafeExamBrowser.Runtime/CompositionRoot.cs b/SafeExamBrowser.Runtime/CompositionRoot.cs index 6518cf09..29599dac 100644 --- a/SafeExamBrowser.Runtime/CompositionRoot.cs +++ b/SafeExamBrowser.Runtime/CompositionRoot.cs @@ -116,15 +116,17 @@ namespace SafeExamBrowser.Runtime var programCopyright = executable.GetCustomAttribute().Copyright; var programTitle = executable.GetCustomAttribute().Title; var programVersion = executable.GetCustomAttribute().InformationalVersion; + + var certificateStore = new CertificateStore(ModuleLogger(nameof(CertificateStore))); var compressor = new GZipCompressor(ModuleLogger(nameof(GZipCompressor))); var passwordEncryption = new PasswordEncryption(ModuleLogger(nameof(PasswordEncryption))); - var publicKeyEncryption = new PublicKeyEncryption(new CertificateStore(), ModuleLogger(nameof(PublicKeyEncryption))); - var symmetricEncryption = new PublicKeySymmetricEncryption(new CertificateStore(), ModuleLogger(nameof(PublicKeySymmetricEncryption)), passwordEncryption); + var publicKeyEncryption = new PublicKeyEncryption(certificateStore, ModuleLogger(nameof(PublicKeyEncryption))); + var symmetricEncryption = new PublicKeySymmetricEncryption(certificateStore, ModuleLogger(nameof(PublicKeySymmetricEncryption)), passwordEncryption); var repositoryLogger = ModuleLogger(nameof(ConfigurationRepository)); var xmlParser = new XmlParser(ModuleLogger(nameof(XmlParser))); var xmlSerializer = new XmlSerializer(ModuleLogger(nameof(XmlSerializer))); - configuration = new ConfigurationRepository(new HashAlgorithm(), repositoryLogger, executable.Location, programCopyright, programTitle, programVersion); + configuration = new ConfigurationRepository(certificateStore, new HashAlgorithm(), repositoryLogger, executable.Location, programCopyright, programTitle, programVersion); appConfig = configuration.InitializeAppConfig(); configuration.Register(new BinaryParser(compressor, new HashAlgorithm(), ModuleLogger(nameof(BinaryParser)), passwordEncryption, publicKeyEncryption, symmetricEncryption, xmlParser));