66 lines
2.0 KiB
C#

using DigitalData.Core.Abstractions.Security;
using Microsoft.IdentityModel.Tokens;
using System.Security.Cryptography;
namespace DigitalData.Core.Security.Cryptographer
{
public class RSAPrivateKey : RSAKeyBase, IAsymmetricPrivateKey, IAsymmetricKey
{
private string? _pem;
public override string Pem
{
#pragma warning disable CS8603 // Possible null reference return.
get => _pem;
#pragma warning restore CS8603 // Possible null reference return.
init
{
_pem = value;
Init();
}
}
public bool IsPemNull => _pem is null;
public bool IsEncrypted { get; init; }
private readonly Lazy<IAsymmetricPublicKey> _lazyPublicKey;
public IAsymmetricPublicKey PublicKey => _lazyPublicKey.Value;
public RSAPrivateKey()
{
_lazyPublicKey = new(() => new RSAPublicKey()
{
Pem = RSA.ExportRSAPublicKeyPem(),
Padding = Padding
});
}
public byte[] Decrypt(byte[] data) => RSA.Decrypt(data, Padding);
public string Decrypt(string data) => RSA.Decrypt(data.Base64ToByte(), Padding).BytesToString();
internal void SetPem(string pem)
{
_pem = pem;
Init();
}
private void Init()
{
if (string.IsNullOrEmpty(_pem))
throw PemIsNullException;
if (IsEncrypted)
RSA.ImportFromEncryptedPem(Pem, Secrets.PBE_PASSWORD.AsSpan());
else
RSA.ImportFromPem(Pem);
}
private InvalidOperationException PemIsNullException => new($"Pem is null or empty. Issuer: {Issuer}, Audience: {Audience}.");
public SigningCredentials CreateSigningCredentials(string algorithm = SecurityAlgorithms.RsaSha256, string? digest = null)
=> digest is null ? new(RsaSecurityKey, algorithm) : new(RsaSecurityKey, algorithm, digest);
}
}