using DigitalData.Core.Abstractions.Security; using DigitalData.Core.Security.Config; using Microsoft.Extensions.Options; using System.Security.Cryptography; namespace DigitalData.Core.Security.Cryptographer { public class RSAFactory : IAsymmetricKeyFactory where TRSAFactoryParams : RSAFactoryParams { protected readonly TRSAFactoryParams _params; public RSAFactory(IOptions options) { options.Value.Init(); _params = options.Value; } public string CreatePrivateKeyPem(int? keySizeInBits = null, bool encrypt = false) => encrypt ? CreateEncryptedPrivateKeyPem(keySizeInBits: keySizeInBits) : RSA.Create(keySizeInBits ?? _params.KeySizeInBits).ExportRSAPrivateKeyPem(); public string CreateEncryptedPrivateKeyPem( PbeEncryptionAlgorithm? pbeEncryptionAlgorithm = null, HashAlgorithmName? hashAlgorithmName = null, int? iterationCount = null, int? keySizeInBits = null, string? password = null) { password ??= _params.PbePassword; 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 IAsymmetricPrivateKey CreatePrivateKey(string pem, string? issuer = null, string? audience = null, bool encrypt = false, RSAEncryptionPadding? padding = null) => new RSAPrivateKey() { Pem = pem, Issuer = issuer ?? string.Empty, Audience = audience ?? string.Empty, IsEncrypted = encrypt, Padding = padding ?? RSAEncryptionPadding.OaepSHA256 }; } }