diff --git a/DigitalData.Core.Abstractions/Security/ICryptFactory.cs b/DigitalData.Core.Abstractions/Security/ICryptFactory.cs index f47513c..9cce682 100644 --- a/DigitalData.Core.Abstractions/Security/ICryptFactory.cs +++ b/DigitalData.Core.Abstractions/Security/ICryptFactory.cs @@ -1,6 +1,30 @@ -namespace DigitalData.Core.Abstractions.Security +using System.Security.Cryptography; + +namespace DigitalData.Core.Abstractions.Security { public interface ICryptFactory { + public int KeySizeInBits { get; init; } + + public string Password { get; init; } + + public PbeEncryptionAlgorithm PbeEncryptionAlgorithm { get; init; } + + public HashAlgorithmName PbeHashAlgorithmName { get; init; } + + public int PbeIterationCount { get; init; } + + public PbeParameters PbeParameters { get; } + + public string EncryptedPrivateKeyPemLabel { get; init; } + + string CreateRSAPrivateKeyPem(int? keySizeInBits = null); + + string CreateEncryptedPrivateKeyPem( + int? keySizeInBits = null, + string? password = null, + PbeEncryptionAlgorithm? pbeEncryptionAlgorithm = null, + HashAlgorithmName? hashAlgorithmName = null, + int? iterationCount = null); } } \ No newline at end of file diff --git a/DigitalData.Core.Security/CryptFactory.cs b/DigitalData.Core.Security/CryptFactory.cs index a70c5ed..9403d44 100644 --- a/DigitalData.Core.Security/CryptFactory.cs +++ b/DigitalData.Core.Security/CryptFactory.cs @@ -1,4 +1,5 @@ using DigitalData.Core.Abstractions.Security; +using System.Security.Cryptography; namespace DigitalData.Core.Security { @@ -7,5 +8,52 @@ namespace DigitalData.Core.Security private static readonly Lazy LazyInstance = new (() => new ()); public static CryptFactory Instance => LazyInstance.Value; + + public int KeySizeInBits { get; init; } = 2048; + + public string Password { get; init; } + + public PbeEncryptionAlgorithm PbeEncryptionAlgorithm { get; init; } = PbeEncryptionAlgorithm.Aes256Cbc; + + public HashAlgorithmName PbeHashAlgorithmName { get; init; } = HashAlgorithmName.SHA256; + + public int PbeIterationCount { get; init; } = 100_000; + + private readonly Lazy _lazyPbeParameters; + + public PbeParameters PbeParameters => _lazyPbeParameters.Value; + + public string EncryptedPrivateKeyPemLabel { get; init; } = "ENCRYPTED PRIVATE KEY"; + + public CryptFactory() + { + _lazyPbeParameters = new(() => new PbeParameters(PbeEncryptionAlgorithm, PbeHashAlgorithmName, PbeIterationCount)); + } + + public string CreateRSAPrivateKeyPem(int? keySizeInBits = null) + => RSA.Create(keySizeInBits ?? KeySizeInBits).ExportRSAPrivateKeyPem(); + + public string CreateEncryptedPrivateKeyPem( + int? keySizeInBits = null, + string? password = null, + PbeEncryptionAlgorithm? pbeEncryptionAlgorithm = null, + HashAlgorithmName? hashAlgorithmName = null, + int? iterationCount = null) + { + password ??= Password; + + var pbeParameters = (pbeEncryptionAlgorithm is null && hashAlgorithmName is null && iterationCount is null) + ? new PbeParameters( + pbeEncryptionAlgorithm ?? PbeEncryptionAlgorithm, + hashAlgorithmName ?? PbeHashAlgorithmName, + iterationCount ?? PbeIterationCount) + : PbeParameters; + + var encryptedPrivateKey = RSA.Create(keySizeInBits ?? KeySizeInBits).ExportEncryptedPkcs8PrivateKey(password.AsSpan(), pbeParameters); + + var pemChars = PemEncoding.Write(EncryptedPrivateKeyPemLabel, encryptedPrivateKey); + + return new string(pemChars); + } } } \ No newline at end of file