From ec2ee67896170d14768fb58ed85b522bfe96736e Mon Sep 17 00:00:00 2001 From: Matthias Gernand Date: Tue, 15 Nov 2022 23:17:57 +0100 Subject: [PATCH] Removed default secrets for the string encryption service. (#49) --- ...era.Extensions.Caching.Abstractions.csproj | 2 +- .../Fluxera.Extensions.Caching.csproj | 4 +- ...xera.Extensions.Common.Abstractions.csproj | 2 +- .../IStringEncryptionService.cs | 22 ++++++ .../StringEncryptionOptions.cs | 17 ++--- .../Fluxera.Extensions.Common.csproj | 6 +- .../PasswordGenerator.cs | 4 +- .../ServiceCollectionExtensions.cs | 20 ++--- .../StringEncryptionOptionsValidator.cs | 45 +++++++++++ .../StringEncryptionService.cs | 75 +++++++++---------- ...ensions.DataManagement.Abstractions.csproj | 4 +- .../Fluxera.Extensions.DataManagement.csproj | 2 +- ...ns.DependencyInjection.Abstractions.csproj | 4 +- ...xera.Extensions.DependencyInjection.csproj | 6 +- ...luxera.Extensions.Http.Abstractions.csproj | 4 +- .../Fluxera.Extensions.Http.csproj | 2 +- .../Handlers/ContentHashResponseHandler.cs | 2 +- ...xtensions.Localization.Abstractions.csproj | 2 +- .../Fluxera.Extensions.Localization.csproj | 4 +- ...uxera.Extensions.OData.Abstractions.csproj | 2 +- .../Fluxera.Extensions.OData.csproj | 2 +- .../ODataClientServiceBase.cs | 18 +++++ ....Extensions.Validation.Abstractions.csproj | 4 +- ...tensions.Validation.DataAnnotations.csproj | 2 +- ...ensions.Validation.FluentValidation.csproj | 2 +- .../Fluxera.Extensions.Validation.csproj | 4 +- .../StringEncryptionServiceTests.cs | 73 ++++++++++++++++++ .../Model/IRepository.cs | 4 +- .../NamedServiceTests.cs | 4 +- .../ObjectAccessorTests.cs | 10 ++- .../HttpClientServiceTests.cs | 2 +- .../ODataClientServiceTests.cs | 2 +- 32 files changed, 254 insertions(+), 102 deletions(-) create mode 100644 src/Fluxera.Extensions.Common/StringEncryptionOptionsValidator.cs create mode 100644 tests/Fluxera.Extensions.Common.UnitTests/StringEncryptionServiceTests.cs diff --git a/src/Fluxera.Extensions.Caching.Abstractions/Fluxera.Extensions.Caching.Abstractions.csproj b/src/Fluxera.Extensions.Caching.Abstractions/Fluxera.Extensions.Caching.Abstractions.csproj index afe7b4d..29122d6 100644 --- a/src/Fluxera.Extensions.Caching.Abstractions/Fluxera.Extensions.Caching.Abstractions.csproj +++ b/src/Fluxera.Extensions.Caching.Abstractions/Fluxera.Extensions.Caching.Abstractions.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + net7.0 diff --git a/src/Fluxera.Extensions.Caching/Fluxera.Extensions.Caching.csproj b/src/Fluxera.Extensions.Caching/Fluxera.Extensions.Caching.csproj index f4a1e63..8d21f35 100644 --- a/src/Fluxera.Extensions.Caching/Fluxera.Extensions.Caching.csproj +++ b/src/Fluxera.Extensions.Caching/Fluxera.Extensions.Caching.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + net7.0 @@ -22,7 +22,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Fluxera.Extensions.Common.Abstractions/Fluxera.Extensions.Common.Abstractions.csproj b/src/Fluxera.Extensions.Common.Abstractions/Fluxera.Extensions.Common.Abstractions.csproj index 6cf09b2..f12b7ce 100644 --- a/src/Fluxera.Extensions.Common.Abstractions/Fluxera.Extensions.Common.Abstractions.csproj +++ b/src/Fluxera.Extensions.Common.Abstractions/Fluxera.Extensions.Common.Abstractions.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + net7.0 diff --git a/src/Fluxera.Extensions.Common.Abstractions/IStringEncryptionService.cs b/src/Fluxera.Extensions.Common.Abstractions/IStringEncryptionService.cs index 73c84ad..01b098d 100644 --- a/src/Fluxera.Extensions.Common.Abstractions/IStringEncryptionService.cs +++ b/src/Fluxera.Extensions.Common.Abstractions/IStringEncryptionService.cs @@ -1,5 +1,7 @@ namespace Fluxera.Extensions.Common { + using System.Threading; + using System.Threading.Tasks; using JetBrains.Annotations; /// @@ -17,6 +19,16 @@ public interface IStringEncryptionService /// Encrypted text string Encrypt(string plainText, string passPhrase = null, byte[] salt = null); + /// + /// Encrypts a text. + /// + /// The text in plain format + /// A phrase to use as the encryption key (optional, uses default if not provided) + /// Salt value (optional, uses default if not provided) + /// + /// Encrypted text + Task EncryptAsync(string plainText, string passPhrase = null, byte[] salt = null, CancellationToken cancellationToken = default); + /// /// Decrypts a text that is encrypted by the method. /// @@ -25,5 +37,15 @@ public interface IStringEncryptionService /// Salt value (optional, uses default if not provided) /// Decrypted text string Decrypt(string cipherText, string passPhrase = null, byte[] salt = null); + + /// + /// Decrypts a text that is encrypted by the method. + /// + /// The text in encrypted format + /// A phrase to use as the encryption key (optional, uses default if not provided) + /// Salt value (optional, uses default if not provided) + /// + /// Decrypted text + Task DecryptAsync(string cipherText, string passPhrase = null, byte[] salt = null, CancellationToken cancellationToken = default); } } diff --git a/src/Fluxera.Extensions.Common.Abstractions/StringEncryptionOptions.cs b/src/Fluxera.Extensions.Common.Abstractions/StringEncryptionOptions.cs index 5f3912f..3f84ec9 100644 --- a/src/Fluxera.Extensions.Common.Abstractions/StringEncryptionOptions.cs +++ b/src/Fluxera.Extensions.Common.Abstractions/StringEncryptionOptions.cs @@ -1,6 +1,5 @@ namespace Fluxera.Extensions.Common { - using System.Text; using JetBrains.Annotations; /// @@ -15,34 +14,28 @@ public sealed class StringEncryptionOptions public StringEncryptionOptions() { this.KeySize = 256; - this.DefaultPassPhrase = "gsKnGZ041HLL4IM8"; - this.InitVectorBytes = Encoding.ASCII.GetBytes("jkE49230Tf093b42"); - this.DefaultSalt = Encoding.ASCII.GetBytes("hgt!16kl"); } /// /// This constant is used to determine the key-size of the encryption algorithm. - /// Default value: 256. + /// The default value is 256. /// public int KeySize { get; set; } /// - /// Default password to encrypt/decrypt texts. - /// It's recommended to set to another value for security. - /// Default value: "gsKnGZ041HLL4IM8" + /// The default password to encrypt/decrypt texts. /// public string DefaultPassPhrase { get; set; } /// /// This constant string is used as a "salt" value for the PasswordDeriveBytes function calls. - /// This size of the IV (in bytes) must = (key-size / 8). Default key-size is 256, so the IV must be - /// 32 bytes long. Using a 16 character string here gives us 32 bytes when converted to a byte array. - /// Default value: Encoding.ASCII.GetBytes("jkE49230Tf093b42") + /// This size of the IV (in bytes) must = (key-size / 16). The default key-size is 256, so the + /// IV must be 16 bytes long. /// public byte[] InitVectorBytes { get; set; } /// - /// Default value: Encoding.ASCII.GetBytes("hgt!16kl") + /// Gets the default salt bytes. /// public byte[] DefaultSalt { get; set; } } diff --git a/src/Fluxera.Extensions.Common/Fluxera.Extensions.Common.csproj b/src/Fluxera.Extensions.Common/Fluxera.Extensions.Common.csproj index 7d3e645..908d6f4 100644 --- a/src/Fluxera.Extensions.Common/Fluxera.Extensions.Common.csproj +++ b/src/Fluxera.Extensions.Common/Fluxera.Extensions.Common.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + net7.0 @@ -22,8 +22,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Fluxera.Extensions.Common/PasswordGenerator.cs b/src/Fluxera.Extensions.Common/PasswordGenerator.cs index 6c8056e..29982b5 100644 --- a/src/Fluxera.Extensions.Common/PasswordGenerator.cs +++ b/src/Fluxera.Extensions.Common/PasswordGenerator.cs @@ -11,13 +11,13 @@ internal sealed class PasswordGenerator : IPasswordGenerator { private static readonly char[] PwdCharArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890!$+-".ToCharArray(); - private readonly RNGCryptoServiceProvider rng; + private readonly RandomNumberGenerator rng; public PasswordGenerator() { this.ConsecutiveCharacters = false; this.RepeatCharacters = true; - this.rng = new RNGCryptoServiceProvider(); + this.rng = RandomNumberGenerator.Create(); } private bool RepeatCharacters { get; } diff --git a/src/Fluxera.Extensions.Common/ServiceCollectionExtensions.cs b/src/Fluxera.Extensions.Common/ServiceCollectionExtensions.cs index 324fd9d..4ba1a66 100644 --- a/src/Fluxera.Extensions.Common/ServiceCollectionExtensions.cs +++ b/src/Fluxera.Extensions.Common/ServiceCollectionExtensions.cs @@ -5,6 +5,7 @@ using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; + using Microsoft.Extensions.Options; /// /// Extension methods for the type. @@ -165,17 +166,7 @@ public static IServiceCollection AddGuidGenerator(this IServiceCollection servic /// The service collection. public static IServiceCollection AddStringEncryptionService(this IServiceCollection services) { - Guard.Against.Null(services); - - // Add logging infrastructure. - services.AddLogging(); - - // Add options infrastructure. - services.AddOptions(); - - services.AddTransient(); - - return services; + return services.AddStringEncryptionService(null); } /// @@ -195,7 +186,12 @@ public static IServiceCollection AddStringEncryptionService(this IServiceCollect // Add options infrastructure. services.AddOptions(); - services.Configure(configureOptions); + if(configureOptions is not null) + { + services.Configure(configureOptions); + } + + services.AddSingleton, StringEncryptionOptionsValidator>(); services.AddTransient(); diff --git a/src/Fluxera.Extensions.Common/StringEncryptionOptionsValidator.cs b/src/Fluxera.Extensions.Common/StringEncryptionOptionsValidator.cs new file mode 100644 index 0000000..bfe5736 --- /dev/null +++ b/src/Fluxera.Extensions.Common/StringEncryptionOptionsValidator.cs @@ -0,0 +1,45 @@ +namespace Fluxera.Extensions.Common +{ + using System.Collections.Generic; + using System.Linq; + using Microsoft.Extensions.Options; + + internal sealed class StringEncryptionOptionsValidator : IValidateOptions + { + public ValidateOptionsResult Validate(string name, StringEncryptionOptions options) + { + IList failures = new List(); + + if(options.KeySize % 8 != 0) + { + failures.Add("The key size must be a multiple of 8"); + } + + if(string.IsNullOrEmpty(options.DefaultPassPhrase)) + { + failures.Add("A default pass phrase must be configured"); + } + + if(options.InitVectorBytes is null || !options.InitVectorBytes.Any()) + { + failures.Add("The init vector bytes must be configured"); + } + else + { + if(options.InitVectorBytes.Length != options.KeySize / 16) + { + failures.Add("The init vector must be of length key-size / 8"); + } + } + + if(options.DefaultSalt is null || !options.DefaultSalt.Any()) + { + failures.Add("The default salt must be configured"); + } + + return failures.Any() + ? ValidateOptionsResult.Fail(failures) + : ValidateOptionsResult.Success; + } + } +} diff --git a/src/Fluxera.Extensions.Common/StringEncryptionService.cs b/src/Fluxera.Extensions.Common/StringEncryptionService.cs index 475bfa9..1ea84f8 100644 --- a/src/Fluxera.Extensions.Common/StringEncryptionService.cs +++ b/src/Fluxera.Extensions.Common/StringEncryptionService.cs @@ -4,6 +4,9 @@ using System.IO; using System.Security.Cryptography; using System.Text; + using System.Threading; + using System.Threading.Tasks; + using Fluxera.Utilities; using Microsoft.Extensions.Options; /// @@ -20,38 +23,35 @@ public StringEncryptionService(IOptions options) public string Encrypt(string plainText, string passPhrase = null, byte[] salt = null) { - if (plainText == null) - { - return null; - } + return AsyncHelper.RunSync(() => this.EncryptAsync(plainText, passPhrase, salt, CancellationToken.None)); + } - if (passPhrase == null) + /// + public async Task EncryptAsync(string plainText, string passPhrase = null, byte[] salt = null, CancellationToken cancellationToken = default) + { + if(plainText == null) { - passPhrase = options.DefaultPassPhrase; + return null; } - if (salt == null) - { - salt = options.DefaultSalt; - } + passPhrase ??= this.options.DefaultPassPhrase; + salt ??= this.options.DefaultSalt; byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText); - using (Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passPhrase, salt)) + using(Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passPhrase, salt, 1000, HashAlgorithmName.SHA256)) { - byte[] keyBytes = password.GetBytes(options.KeySize / 8); - using (Aes symmetricKey = Aes.Create()) + byte[] keyBytes = password.GetBytes(this.options.KeySize / 8); + using(Aes symmetricKey = Aes.Create()) { symmetricKey.Mode = CipherMode.CBC; - using (ICryptoTransform cryptoTransform = - symmetricKey.CreateEncryptor(keyBytes, options.InitVectorBytes)) + using(ICryptoTransform cryptoTransform = symmetricKey.CreateEncryptor(keyBytes, this.options.InitVectorBytes)) { - using (MemoryStream memoryStream = new MemoryStream()) + using(MemoryStream memoryStream = new MemoryStream()) { - using (CryptoStream cryptoStream = - new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write)) + await using(CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write)) { - cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length); - cryptoStream.FlushFinalBlock(); + await cryptoStream.WriteAsync(plainTextBytes, 0, plainTextBytes.Length, cancellationToken); + await cryptoStream.FlushFinalBlockAsync(cancellationToken); byte[] cipherTextBytes = memoryStream.ToArray(); return Convert.ToBase64String(cipherTextBytes); } @@ -63,38 +63,35 @@ public string Encrypt(string plainText, string passPhrase = null, byte[] salt = public string Decrypt(string cipherText, string passPhrase = null, byte[] salt = null) { - if (string.IsNullOrEmpty(cipherText)) - { - return null; - } + return AsyncHelper.RunSync(() => this.DecryptAsync(cipherText, passPhrase, salt, CancellationToken.None)); + } - if (passPhrase == null) + /// + public async Task DecryptAsync(string cipherText, string passPhrase = null, byte[] salt = null, CancellationToken cancellationToken = default) + { + if(string.IsNullOrEmpty(cipherText)) { - passPhrase = options.DefaultPassPhrase; + return null; } - if (salt == null) - { - salt = options.DefaultSalt; - } + passPhrase ??= this.options.DefaultPassPhrase; + salt ??= this.options.DefaultSalt; byte[] cipherTextBytes = Convert.FromBase64String(cipherText); - using (Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passPhrase, salt)) + using(Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passPhrase, salt, 1000, HashAlgorithmName.SHA256)) { - byte[] keyBytes = password.GetBytes(options.KeySize / 8); - using (Aes symmetricKey = Aes.Create()) + byte[] keyBytes = password.GetBytes(this.options.KeySize / 8); + using(Aes symmetricKey = Aes.Create()) { symmetricKey.Mode = CipherMode.CBC; - using (ICryptoTransform cryptoTransform = - symmetricKey.CreateDecryptor(keyBytes, options.InitVectorBytes)) + using(ICryptoTransform cryptoTransform = symmetricKey.CreateDecryptor(keyBytes, this.options.InitVectorBytes)) { - using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes)) + using(MemoryStream memoryStream = new MemoryStream(cipherTextBytes)) { - using (CryptoStream cryptoStream = - new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Read)) + await using(CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Read)) { byte[] plainTextBytes = new byte[cipherTextBytes.Length]; - int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length); + int decryptedByteCount = await cryptoStream.ReadAsync(plainTextBytes, 0, plainTextBytes.Length, cancellationToken); return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount); } } diff --git a/src/Fluxera.Extensions.DataManagement.Abstractions/Fluxera.Extensions.DataManagement.Abstractions.csproj b/src/Fluxera.Extensions.DataManagement.Abstractions/Fluxera.Extensions.DataManagement.Abstractions.csproj index 5f9c1d6..515e186 100644 --- a/src/Fluxera.Extensions.DataManagement.Abstractions/Fluxera.Extensions.DataManagement.Abstractions.csproj +++ b/src/Fluxera.Extensions.DataManagement.Abstractions/Fluxera.Extensions.DataManagement.Abstractions.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + net7.0 @@ -23,7 +23,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Fluxera.Extensions.DataManagement/Fluxera.Extensions.DataManagement.csproj b/src/Fluxera.Extensions.DataManagement/Fluxera.Extensions.DataManagement.csproj index 4bfbe52..250c126 100644 --- a/src/Fluxera.Extensions.DataManagement/Fluxera.Extensions.DataManagement.csproj +++ b/src/Fluxera.Extensions.DataManagement/Fluxera.Extensions.DataManagement.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + net7.0 diff --git a/src/Fluxera.Extensions.DependencyInjection.Abstractions/Fluxera.Extensions.DependencyInjection.Abstractions.csproj b/src/Fluxera.Extensions.DependencyInjection.Abstractions/Fluxera.Extensions.DependencyInjection.Abstractions.csproj index 36d3323..736e2a4 100644 --- a/src/Fluxera.Extensions.DependencyInjection.Abstractions/Fluxera.Extensions.DependencyInjection.Abstractions.csproj +++ b/src/Fluxera.Extensions.DependencyInjection.Abstractions/Fluxera.Extensions.DependencyInjection.Abstractions.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + net7.0 @@ -23,7 +23,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Fluxera.Extensions.DependencyInjection/Fluxera.Extensions.DependencyInjection.csproj b/src/Fluxera.Extensions.DependencyInjection/Fluxera.Extensions.DependencyInjection.csproj index ac11384..6d9e3db 100644 --- a/src/Fluxera.Extensions.DependencyInjection/Fluxera.Extensions.DependencyInjection.csproj +++ b/src/Fluxera.Extensions.DependencyInjection/Fluxera.Extensions.DependencyInjection.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + net7.0 @@ -22,8 +22,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Fluxera.Extensions.Http.Abstractions/Fluxera.Extensions.Http.Abstractions.csproj b/src/Fluxera.Extensions.Http.Abstractions/Fluxera.Extensions.Http.Abstractions.csproj index 2f4bd6e..3e15195 100644 --- a/src/Fluxera.Extensions.Http.Abstractions/Fluxera.Extensions.Http.Abstractions.csproj +++ b/src/Fluxera.Extensions.Http.Abstractions/Fluxera.Extensions.Http.Abstractions.csproj @@ -1,7 +1,7 @@ - netstandard2.1 + net7.0 @@ -23,7 +23,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Fluxera.Extensions.Http/Fluxera.Extensions.Http.csproj b/src/Fluxera.Extensions.Http/Fluxera.Extensions.Http.csproj index ac65d08..34fd617 100644 --- a/src/Fluxera.Extensions.Http/Fluxera.Extensions.Http.csproj +++ b/src/Fluxera.Extensions.Http/Fluxera.Extensions.Http.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + net7.0 diff --git a/src/Fluxera.Extensions.Http/Handlers/ContentHashResponseHandler.cs b/src/Fluxera.Extensions.Http/Handlers/ContentHashResponseHandler.cs index f8fb4e1..a74f126 100644 --- a/src/Fluxera.Extensions.Http/Handlers/ContentHashResponseHandler.cs +++ b/src/Fluxera.Extensions.Http/Handlers/ContentHashResponseHandler.cs @@ -20,7 +20,7 @@ public ContentHashResponseHandler(IHashCalculator hashCalculator) protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { HttpResponseMessage response = await base.SendAsync(request, cancellationToken); - if(!response.IsSuccessStatusCode || (response.Content == null)) + if(!response.IsSuccessStatusCode) { return response; } diff --git a/src/Fluxera.Extensions.Localization.Abstractions/Fluxera.Extensions.Localization.Abstractions.csproj b/src/Fluxera.Extensions.Localization.Abstractions/Fluxera.Extensions.Localization.Abstractions.csproj index b39aa0f..b5cf6c4 100644 --- a/src/Fluxera.Extensions.Localization.Abstractions/Fluxera.Extensions.Localization.Abstractions.csproj +++ b/src/Fluxera.Extensions.Localization.Abstractions/Fluxera.Extensions.Localization.Abstractions.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + net7.0 diff --git a/src/Fluxera.Extensions.Localization/Fluxera.Extensions.Localization.csproj b/src/Fluxera.Extensions.Localization/Fluxera.Extensions.Localization.csproj index 27ee8f2..1474557 100644 --- a/src/Fluxera.Extensions.Localization/Fluxera.Extensions.Localization.csproj +++ b/src/Fluxera.Extensions.Localization/Fluxera.Extensions.Localization.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + net7.0 @@ -22,7 +22,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Fluxera.Extensions.OData.Abstractions/Fluxera.Extensions.OData.Abstractions.csproj b/src/Fluxera.Extensions.OData.Abstractions/Fluxera.Extensions.OData.Abstractions.csproj index f158f1a..b4f7fb7 100644 --- a/src/Fluxera.Extensions.OData.Abstractions/Fluxera.Extensions.OData.Abstractions.csproj +++ b/src/Fluxera.Extensions.OData.Abstractions/Fluxera.Extensions.OData.Abstractions.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + net7.0 diff --git a/src/Fluxera.Extensions.OData/Fluxera.Extensions.OData.csproj b/src/Fluxera.Extensions.OData/Fluxera.Extensions.OData.csproj index ec91468..8edeba4 100644 --- a/src/Fluxera.Extensions.OData/Fluxera.Extensions.OData.csproj +++ b/src/Fluxera.Extensions.OData/Fluxera.Extensions.OData.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + net7.0 diff --git a/src/Fluxera.Extensions.OData/ODataClientServiceBase.cs b/src/Fluxera.Extensions.OData/ODataClientServiceBase.cs index 233ef0c..742edb8 100644 --- a/src/Fluxera.Extensions.OData/ODataClientServiceBase.cs +++ b/src/Fluxera.Extensions.OData/ODataClientServiceBase.cs @@ -69,6 +69,8 @@ protected ODataClientServiceBase(string name, string collectionName, IODataClien protected async Task ExecuteFunctionScalarAsync(object parameters = null, CancellationToken cancellationToken = default, [CallerMemberName] string functionName = null) where TResult : struct, IConvertible { + functionName = Guard.Against.NullOrWhiteSpace(functionName); + IBoundClient boundClient = this.ODataClient .For(this.CollectionName) .Function(functionName); @@ -90,6 +92,8 @@ protected async Task ExecuteFunctionScalarAsync(object paramet /// protected async Task ExecuteFunctionSingleAsync(object parameters = null, CancellationToken cancellationToken = default, [CallerMemberName] string functionName = null) { + functionName = Guard.Against.NullOrWhiteSpace(functionName); + IBoundClient boundClient = this.ODataClient .For(this.CollectionName) .Function(functionName); @@ -111,6 +115,8 @@ protected async Task ExecuteFunctionSingleAsync(object parameters = null, Can /// protected async Task> ExecuteFunctionEnumerableAsync(object parameters = null, CancellationToken cancellationToken = default, [CallerMemberName] string functionName = null) { + functionName = Guard.Against.NullOrWhiteSpace(functionName); + IBoundClient boundClient = this.ODataClient .For(this.CollectionName) .Function(functionName); @@ -133,6 +139,8 @@ protected async Task> ExecuteFunctionEnumerableAsync(obje /// protected async Task ExecuteActionAsync(object parameters = null, CancellationToken cancellationToken = default, [CallerMemberName] string actionName = null) { + actionName = Guard.Against.NullOrWhiteSpace(actionName); + IBoundClient boundClient = this.ODataClient .For(this.CollectionName) .Action(actionName); @@ -154,6 +162,8 @@ protected async Task ExecuteActionAsync(object parameters = null, CancellationTo /// protected async Task ExecuteActionAsync(T instance, CancellationToken cancellationToken = default, [CallerMemberName] string actionName = null) { + actionName = Guard.Against.NullOrWhiteSpace(actionName); + IBoundClient boundClient = this.ODataClient .For(this.CollectionName) .Key(instance.ID) @@ -171,6 +181,8 @@ protected async Task ExecuteActionAsync(T instance, CancellationToken cancellati /// protected async Task ExecuteActionSingleAsync(T instance, CancellationToken cancellationToken = default, [CallerMemberName] string actionName = null) { + actionName = Guard.Against.NullOrWhiteSpace(actionName); + IBoundClient boundClient = this.ODataClient .For(this.CollectionName) .Key(instance.ID) @@ -190,6 +202,8 @@ protected async Task ExecuteActionSingleAsync(T instance, CancellationToken c protected async Task ExecuteActionScalar(object parameters = null, CancellationToken cancellationToken = default, [CallerMemberName] string actionName = null) where TResult : struct, IConvertible { + actionName = Guard.Against.NullOrWhiteSpace(actionName); + IBoundClient boundClient = this.ODataClient .For(this.CollectionName) .Action(actionName); @@ -211,6 +225,8 @@ protected async Task ExecuteActionScalar(object parameters = n /// protected async Task ExecuteActionSingleAsync(object parameters = null, CancellationToken cancellationToken = default, [CallerMemberName] string actionName = null) { + actionName = Guard.Against.NullOrWhiteSpace(actionName); + IBoundClient boundClient = this.ODataClient .For(this.CollectionName) .Action(actionName); @@ -232,6 +248,8 @@ protected async Task ExecuteActionSingleAsync(object parameters = null, Cance /// protected async Task> ExecuteActionEnumerableAsync(object parameters = null, CancellationToken cancellationToken = default, [CallerMemberName] string actionName = null) { + actionName = Guard.Against.NullOrWhiteSpace(actionName); + IBoundClient boundClient = this.ODataClient .For(this.CollectionName) .Action(actionName); diff --git a/src/Fluxera.Extensions.Validation.Abstractions/Fluxera.Extensions.Validation.Abstractions.csproj b/src/Fluxera.Extensions.Validation.Abstractions/Fluxera.Extensions.Validation.Abstractions.csproj index 56fb590..fea8af7 100644 --- a/src/Fluxera.Extensions.Validation.Abstractions/Fluxera.Extensions.Validation.Abstractions.csproj +++ b/src/Fluxera.Extensions.Validation.Abstractions/Fluxera.Extensions.Validation.Abstractions.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + net7.0 @@ -23,7 +23,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Fluxera.Extensions.Validation.DataAnnotations/Fluxera.Extensions.Validation.DataAnnotations.csproj b/src/Fluxera.Extensions.Validation.DataAnnotations/Fluxera.Extensions.Validation.DataAnnotations.csproj index 902474a..53ce0b7 100644 --- a/src/Fluxera.Extensions.Validation.DataAnnotations/Fluxera.Extensions.Validation.DataAnnotations.csproj +++ b/src/Fluxera.Extensions.Validation.DataAnnotations/Fluxera.Extensions.Validation.DataAnnotations.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + net7.0 diff --git a/src/Fluxera.Extensions.Validation.FluentValidation/Fluxera.Extensions.Validation.FluentValidation.csproj b/src/Fluxera.Extensions.Validation.FluentValidation/Fluxera.Extensions.Validation.FluentValidation.csproj index 4f906ae..e6bf8f7 100644 --- a/src/Fluxera.Extensions.Validation.FluentValidation/Fluxera.Extensions.Validation.FluentValidation.csproj +++ b/src/Fluxera.Extensions.Validation.FluentValidation/Fluxera.Extensions.Validation.FluentValidation.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + net7.0 diff --git a/src/Fluxera.Extensions.Validation/Fluxera.Extensions.Validation.csproj b/src/Fluxera.Extensions.Validation/Fluxera.Extensions.Validation.csproj index 5d0e292..50bd4ec 100644 --- a/src/Fluxera.Extensions.Validation/Fluxera.Extensions.Validation.csproj +++ b/src/Fluxera.Extensions.Validation/Fluxera.Extensions.Validation.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + net7.0 @@ -22,7 +22,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/Fluxera.Extensions.Common.UnitTests/StringEncryptionServiceTests.cs b/tests/Fluxera.Extensions.Common.UnitTests/StringEncryptionServiceTests.cs new file mode 100644 index 0000000..35b2da1 --- /dev/null +++ b/tests/Fluxera.Extensions.Common.UnitTests/StringEncryptionServiceTests.cs @@ -0,0 +1,73 @@ +namespace Fluxera.Extensions.Common.UnitTests +{ + using System; + using System.Text; + using System.Threading.Tasks; + using FluentAssertions; + using Microsoft.Extensions.DependencyInjection; + using NUnit.Framework; + + [TestFixture] + public class StringEncryptionServiceTests + { + [SetUp] + public void SetUp() + { + IServiceCollection services = new ServiceCollection(); + services.AddStringEncryptionService(); + services.Configure(options => + { + options.DefaultPassPhrase = "password"; + options.DefaultSalt = Encoding.ASCII.GetBytes("12345678"); + options.InitVectorBytes = Encoding.ASCII.GetBytes("1234567890abcdef"); + }); + + IServiceProvider serviceProvider = services.BuildServiceProvider(); + this.stringEncryptionService = serviceProvider.GetRequiredService(); + } + + private IStringEncryptionService stringEncryptionService; + + [Test] + public void ShouldDecryptString() + { + const string str = "Hello, World!"; + + string encrypted = this.stringEncryptionService.Encrypt(str); + string decrypted = this.stringEncryptionService.Decrypt(encrypted); + + decrypted.Should().Be(str); + } + + [Test] + public async Task ShouldDecryptStringAsync() + { + const string str = "Hello, World!"; + + string encrypted = await this.stringEncryptionService.EncryptAsync(str); + string decrypted = await this.stringEncryptionService.DecryptAsync(encrypted); + + decrypted.Should().Be(str); + } + + [Test] + public void ShouldEncryptString() + { + const string str = "Hello, World!"; + + string encrypted = this.stringEncryptionService.Encrypt(str); + + encrypted.Should().NotBe(str); + } + + [Test] + public async Task ShouldEncryptStringAsync() + { + const string str = "Hello, World!"; + + string encrypted = await this.stringEncryptionService.EncryptAsync(str); + + encrypted.Should().NotBe(str); + } + } +} diff --git a/tests/Fluxera.Extensions.DependencyInjection.UnitTests/Model/IRepository.cs b/tests/Fluxera.Extensions.DependencyInjection.UnitTests/Model/IRepository.cs index 863f152..291605e 100644 --- a/tests/Fluxera.Extensions.DependencyInjection.UnitTests/Model/IRepository.cs +++ b/tests/Fluxera.Extensions.DependencyInjection.UnitTests/Model/IRepository.cs @@ -1,4 +1,6 @@ -namespace Fluxera.Extensions.DependencyInjection.UnitTests.Model +// ReSharper disable UnusedTypeParameter + +namespace Fluxera.Extensions.DependencyInjection.UnitTests.Model { public interface IRepository { diff --git a/tests/Fluxera.Extensions.DependencyInjection.UnitTests/NamedServiceTests.cs b/tests/Fluxera.Extensions.DependencyInjection.UnitTests/NamedServiceTests.cs index 3612a62..bbf1720 100644 --- a/tests/Fluxera.Extensions.DependencyInjection.UnitTests/NamedServiceTests.cs +++ b/tests/Fluxera.Extensions.DependencyInjection.UnitTests/NamedServiceTests.cs @@ -1,4 +1,6 @@ -namespace Fluxera.Extensions.DependencyInjection.UnitTests +// ReSharper disable PossibleMultipleEnumeration + +namespace Fluxera.Extensions.DependencyInjection.UnitTests { using System; using System.Collections.Generic; diff --git a/tests/Fluxera.Extensions.DependencyInjection.UnitTests/ObjectAccessorTests.cs b/tests/Fluxera.Extensions.DependencyInjection.UnitTests/ObjectAccessorTests.cs index e6fb721..b1c649e 100644 --- a/tests/Fluxera.Extensions.DependencyInjection.UnitTests/ObjectAccessorTests.cs +++ b/tests/Fluxera.Extensions.DependencyInjection.UnitTests/ObjectAccessorTests.cs @@ -1,4 +1,8 @@ -namespace Fluxera.Extensions.DependencyInjection.UnitTests +// ReSharper disable PossibleMultipleEnumeration + +// ReSharper disable LocalVariableHidesMember + +namespace Fluxera.Extensions.DependencyInjection.UnitTests { using System; using System.Collections.Generic; @@ -147,7 +151,7 @@ public void ShouldThrowOnGetObjectFromServiceProvider() // Act Action action = () => { - IAnotherTestService testService = this.serviceProvider.GetObject(); + this.serviceProvider.GetObject(); }; action.Should().Throw(); @@ -159,7 +163,7 @@ public void ShouldThrowOnGetObjectFromServices() // Act Action action = () => { - IAnotherTestService testService = this.services.GetObject(); + this.services.GetObject(); }; action.Should().Throw(); diff --git a/tests/Fluxera.Extensions.Http.UnitTests/HttpClientServiceTests.cs b/tests/Fluxera.Extensions.Http.UnitTests/HttpClientServiceTests.cs index e7c4f4c..199d66f 100644 --- a/tests/Fluxera.Extensions.Http.UnitTests/HttpClientServiceTests.cs +++ b/tests/Fluxera.Extensions.Http.UnitTests/HttpClientServiceTests.cs @@ -19,7 +19,7 @@ public void ShouldCreateNamedHttpClientService() }); services.AddHttpClientService( - (context, serviceProvider) => new TestHttpClientService(context.Name, context.HttpClient, context.Options)); + (context, _) => new TestHttpClientService(context.Name, context.HttpClient, context.Options)); IServiceProvider serviceProvider = services.BuildServiceProvider(); diff --git a/tests/Fluxera.Extensions.OData.UnitTests/ODataClientServiceTests.cs b/tests/Fluxera.Extensions.OData.UnitTests/ODataClientServiceTests.cs index d6c9d9b..f31593b 100644 --- a/tests/Fluxera.Extensions.OData.UnitTests/ODataClientServiceTests.cs +++ b/tests/Fluxera.Extensions.OData.UnitTests/ODataClientServiceTests.cs @@ -20,7 +20,7 @@ public void ShouldCreateNamedODataClientService() }); services.AddODataClientService("People", - (context, serviceProvider) => new TestODataClientService(context.Name, context.CollectionName, context.ODataClient, context.Options)); + (context, _) => new TestODataClientService(context.Name, context.CollectionName, context.ODataClient, context.Options)); IServiceProvider serviceProvider = services.BuildServiceProvider();