diff --git a/DigitalData.Core.Security/Config/RSAFactoryParams.cs b/DigitalData.Core.Security/Config/RSAFactoryParams.cs index 2351b3e..62e5974 100644 --- a/DigitalData.Core.Security/Config/RSAFactoryParams.cs +++ b/DigitalData.Core.Security/Config/RSAFactoryParams.cs @@ -6,13 +6,13 @@ namespace DigitalData.Core.Security.Config { public class RSAFactoryParams { - public int KeySizeInBits { get; init; } = 2048; + public int KeySizeInBits { get; init; } = Default.KeySizeInBits; - public string PbePassword { internal get; init; } = Secrets.PBE_PASSWORD; + public string PbePassword { internal get; init; } = Default.PbePassword; - public PbeEncryptionAlgorithm PbeEncryptionAlgorithm { get; init; } = PbeEncryptionAlgorithm.Aes256Cbc; + public PbeEncryptionAlgorithm PbeEncryptionAlgorithm { get; init; } = Default.PbeEncryptionAlgorithm; - public HashAlgorithmName PbeHashAlgorithm { get; init; } = HashAlgorithmName.SHA256; + public HashAlgorithmName PbeHashAlgorithm { get; init; } = Default.PbeHashAlgorithm; // TODO: add as json converter to IConfigurIConfiguration.Config public string PbeHashAlgorithmName @@ -23,9 +23,9 @@ namespace DigitalData.Core.Security.Config : new(value); } - public int PbeIterationCount { get; init; } = 100_000; + public int PbeIterationCount { get; init; } = Default.PbeIterationCount; - public string EncryptedPrivateKeyPemLabel { get; init; } = "ENCRYPTED PRIVATE KEY"; + public string EncryptedPrivateKeyPemLabel { get; init; } = Default.EncryptedPrivateKeyPemLabel; private readonly Lazy _lazyPbeParameters; @@ -36,5 +36,22 @@ namespace DigitalData.Core.Security.Config { _lazyPbeParameters = new(() => new PbeParameters(PbeEncryptionAlgorithm, PbeHashAlgorithm, PbeIterationCount)); } + + public static class Default + { + public static readonly int KeySizeInBits = 2048; + + public static readonly string PbePassword = Secrets.PBE_PASSWORD; + + public static readonly PbeEncryptionAlgorithm PbeEncryptionAlgorithm = PbeEncryptionAlgorithm.Aes256Cbc; + + public static readonly HashAlgorithmName PbeHashAlgorithm = HashAlgorithmName.SHA256; + + public static readonly int PbeIterationCount = 100_000; + + public static readonly string EncryptedPrivateKeyPemLabel = "ENCRYPTED PRIVATE KEY"; + + public static readonly PbeParameters PbeParameters = new(PbeEncryptionAlgorithm, PbeHashAlgorithm, PbeIterationCount); + } } } \ No newline at end of file diff --git a/DigitalData.Core.Security/CryptoFactory.cs b/DigitalData.Core.Security/CryptoFactory.cs index 588fddd..8b44213 100644 --- a/DigitalData.Core.Security/CryptoFactory.cs +++ b/DigitalData.Core.Security/CryptoFactory.cs @@ -4,35 +4,38 @@ using DigitalData.Core.Security.RSAKey; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -namespace DigitalData.Core.Security +namespace DigitalData.Core.Security; + +public class CryptoFactory : RSAFactory, ICryptoFactory, IAsymmetricKeyFactory { - public class CryptoFactory : RSAFactory, ICryptoFactory, IAsymmetricKeyFactory + private readonly CryptoFactoryParams _params; + + public IEnumerable Decryptors { get; } + + /// + /// It is a separate decryptor for permanently stored encrypted data. It is assigned to the first Default decryptor by default. + /// + public IAsymmetricDecryptor VaultDecryptor { get; } + + public IEnumerable TokenDescriptors { get; init; } = new List(); + + public CryptoFactory(IOptions cryptoFactoryParamsOptions, ILogger? logger = null) { - public IEnumerable Decryptors { get; } - - /// - /// It is a separate decryptor for permanently stored encrypted data. It is assigned to the first Default decryptor by default. - /// - public IAsymmetricDecryptor VaultDecryptor { get; } + _params = cryptoFactoryParamsOptions.Value; - public IEnumerable TokenDescriptors { get; init; } = new List(); + logger?.LogInformation("Core.Secrets version: {Version}, Created on: {CreationDate}.", Secrets.Version, Secrets.CreationDate.ToString("dd.MM.yyyy")); - public CryptoFactory(IOptions options, ILogger? logger = null) : base(options) - { - logger?.LogInformation("Core.Secrets version: {Version}, Created on: {CreationDate}.", Secrets.Version, Secrets.CreationDate.ToString("dd.MM.yyyy")); + if (!_params.Decryptors.Any()) + throw new InvalidOperationException( + "Any decryptor is not found. Ensure that at least one decryptor is configured in the provided parameters. " + + "This issue typically arises if the configuration for decryptors is incomplete or missing. " + + "Check the 'Decryptors' collection in the configuration and verify that it contains valid entries." + ); - if (!_params.Decryptors.Any()) - throw new InvalidOperationException( - "Any decryptor is not found. Ensure that at least one decryptor is configured in the provided parameters. " + - "This issue typically arises if the configuration for decryptors is incomplete or missing. " + - "Check the 'Decryptors' collection in the configuration and verify that it contains valid entries." - ); + Decryptors = _params.Decryptors; - Decryptors = _params.Decryptors; + TokenDescriptors = _params.TokenDescriptors; - TokenDescriptors = _params.TokenDescriptors; - - VaultDecryptor = _params.VaultDecryptor ?? Decryptors.First(); - } + VaultDecryptor = _params.VaultDecryptor ?? Decryptors.First(); } } \ No newline at end of file diff --git a/DigitalData.Core.Security/RSAKey/RSAFactory.cs b/DigitalData.Core.Security/RSAKey/RSAFactory.cs index 82ce426..6acbc95 100644 --- a/DigitalData.Core.Security/RSAKey/RSAFactory.cs +++ b/DigitalData.Core.Security/RSAKey/RSAFactory.cs @@ -1,65 +1,54 @@ using DigitalData.Core.Abstractions.Security; using DigitalData.Core.Security.Config; -using Microsoft.Extensions.Options; using System.Security.Cryptography; -namespace DigitalData.Core.Security.RSAKey +namespace DigitalData.Core.Security.RSAKey; + +public class RSAFactory : IAsymmetricKeyFactory { - public class RSAFactory : IAsymmetricKeyFactory where TRSAFactoryParams : RSAFactoryParams + public string CreatePrivateKeyPem(int? keySizeInBits = null, bool encrypt = false) => encrypt + ? CreateEncryptedPrivateKeyPem(keySizeInBits: keySizeInBits) + : RSA.Create(keySizeInBits ?? RSAFactoryParams.Default.KeySizeInBits).ExportRSAPrivateKeyPem(); + + public string CreateEncryptedPrivateKeyPem( + PbeEncryptionAlgorithm? pbeEncryptionAlgorithm = null, + HashAlgorithmName? hashAlgorithmName = null, + int? iterationCount = null, + int? keySizeInBits = null, + string? password = null) { - protected readonly TRSAFactoryParams _params; + password ??= RSAFactoryParams.Default.PbePassword; - public RSAFactory(IOptions options) - { - _params = options.Value; - } + var pbeParameters = new PbeParameters( + pbeEncryptionAlgorithm ?? RSAFactoryParams.Default.PbeEncryptionAlgorithm, + hashAlgorithmName ?? RSAFactoryParams.Default.PbeHashAlgorithm, + iterationCount ?? RSAFactoryParams.Default.PbeIterationCount); - public string CreatePrivateKeyPem(int? keySizeInBits = null, bool encrypt = false) => encrypt - ? CreateEncryptedPrivateKeyPem(keySizeInBits: keySizeInBits) - : RSA.Create(keySizeInBits ?? _params.KeySizeInBits).ExportRSAPrivateKeyPem(); + var encryptedPrivateKey = RSA.Create(keySizeInBits ?? RSAFactoryParams.Default.KeySizeInBits).ExportEncryptedPkcs8PrivateKey(password.AsSpan(), pbeParameters); - public string CreateEncryptedPrivateKeyPem( - PbeEncryptionAlgorithm? pbeEncryptionAlgorithm = null, - HashAlgorithmName? hashAlgorithmName = null, - int? iterationCount = null, - int? keySizeInBits = null, - string? password = null) - { - password ??= _params.PbePassword; + var pemChars = PemEncoding.Write(RSAFactoryParams.Default.EncryptedPrivateKeyPemLabel, encryptedPrivateKey); - var pbeParameters = pbeEncryptionAlgorithm is null && hashAlgorithmName is null && iterationCount is null - ? new PbeParameters( - pbeEncryptionAlgorithm ?? _params.PbeEncryptionAlgorithm, - hashAlgorithmName ?? _params.PbeHashAlgorithm, - iterationCount ?? _params.PbeIterationCount) - : _params.PbeParameters; - - var encryptedPrivateKey = RSA.Create(keySizeInBits ?? _params.KeySizeInBits).ExportEncryptedPkcs8PrivateKey(password.AsSpan(), pbeParameters); - - var pemChars = PemEncoding.Write(_params.EncryptedPrivateKeyPemLabel, encryptedPrivateKey); - - return new string(pemChars); - } - - public string CreateEncryptedPrivateKeyPem( - PbeParameters pbeParameters, - int? keySizeInBits = null, - string? password = null) - { - password ??= _params.PbePassword; - - var encryptedPrivateKey = RSA.Create(keySizeInBits ?? _params.KeySizeInBits).ExportEncryptedPkcs8PrivateKey(password.AsSpan(), pbeParameters); - - var pemChars = PemEncoding.Write(_params.EncryptedPrivateKeyPemLabel, encryptedPrivateKey); - - return new string(pemChars); - } - - public IAsymmetricDecryptor CreateDecryptor(string pem, string? issuer = null, string? audience = null, bool encrypt = false, RSAEncryptionPadding? padding = null) => new RSADecryptor() - { - Content = pem, - IsEncrypted = encrypt, - Padding = padding ?? RSAEncryptionPadding.OaepSHA256 - }; + return new string(pemChars); } + + public string CreateEncryptedPrivateKeyPem( + PbeParameters pbeParameters, + int? keySizeInBits = null, + string? password = null) + { + password ??= RSAFactoryParams.Default.PbePassword; + + var encryptedPrivateKey = RSA.Create(keySizeInBits ?? RSAFactoryParams.Default.KeySizeInBits).ExportEncryptedPkcs8PrivateKey(password.AsSpan(), pbeParameters); + + var pemChars = PemEncoding.Write(RSAFactoryParams.Default.EncryptedPrivateKeyPemLabel, encryptedPrivateKey); + + return new string(pemChars); + } + + public IAsymmetricDecryptor CreateDecryptor(string pem, string? issuer = null, string? audience = null, bool encrypt = false, RSAEncryptionPadding? padding = null) => new RSADecryptor() + { + Content = pem, + IsEncrypted = encrypt, + Padding = padding ?? RSAEncryptionPadding.OaepSHA256 + }; } \ No newline at end of file