refactor(DigitalData.Core.Security): Umbenennung des Unternamensraums von Cryptographer in RSAKey
This commit is contained in:
68
DigitalData.Core.Security/RSAKey/RSAFactory.cs
Normal file
68
DigitalData.Core.Security/RSAKey/RSAFactory.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using DigitalData.Core.Abstractions.Security;
|
||||
using DigitalData.Core.Security.Config;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace DigitalData.Core.Security.RSAKey
|
||||
{
|
||||
public class RSAFactory<TRSAFactoryParams> : IAsymmetricKeyFactory where TRSAFactoryParams : RSAFactoryParams
|
||||
{
|
||||
protected readonly TRSAFactoryParams _params;
|
||||
|
||||
public RSAFactory(IOptions<TRSAFactoryParams> 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
|
||||
};
|
||||
}
|
||||
}
|
||||
38
DigitalData.Core.Security/RSAKey/RSAKeyBase.cs
Normal file
38
DigitalData.Core.Security/RSAKey/RSAKeyBase.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using DigitalData.Core.Abstractions.Security;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace DigitalData.Core.Security.RSAKey
|
||||
{
|
||||
public class RSAKeyBase : IAsymmetricKey
|
||||
{
|
||||
public virtual string Pem { get; init; }
|
||||
|
||||
public RSAEncryptionPadding Padding { get; init; } = RSAEncryptionPadding.OaepSHA256;
|
||||
|
||||
// TODO: add as json converter to IConfigurIConfiguration.Config
|
||||
public string PaddingName
|
||||
{
|
||||
get => Padding.ToString();
|
||||
init => Padding = typeof(RSAEncryptionPadding).GetProperty(value, BindingFlags.Public | BindingFlags.Static)?.GetValue(null) as RSAEncryptionPadding ?? throw new ArgumentException($"Padding '{value}' not found.");
|
||||
}
|
||||
|
||||
protected virtual RSA RSA { get; } = RSA.Create();
|
||||
|
||||
public string Issuer { get; init; } = string.Empty;
|
||||
|
||||
public string Audience { get; init; } = string.Empty;
|
||||
|
||||
private readonly Lazy<RsaSecurityKey> _lazyRsaSecurityKey;
|
||||
|
||||
public RsaSecurityKey RsaSecurityKey => _lazyRsaSecurityKey.Value;
|
||||
|
||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
internal RSAKeyBase()
|
||||
{
|
||||
_lazyRsaSecurityKey = new(() => new RsaSecurityKey(RSA));
|
||||
}
|
||||
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
}
|
||||
}
|
||||
66
DigitalData.Core.Security/RSAKey/RSAPrivateKey.cs
Normal file
66
DigitalData.Core.Security/RSAKey/RSAPrivateKey.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using DigitalData.Core.Abstractions.Security;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace DigitalData.Core.Security.RSAKey
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
23
DigitalData.Core.Security/RSAKey/RSAPublicKey.cs
Normal file
23
DigitalData.Core.Security/RSAKey/RSAPublicKey.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using DigitalData.Core.Abstractions.Security;
|
||||
|
||||
namespace DigitalData.Core.Security.RSAKey
|
||||
{
|
||||
public class RSAPublicKey : RSAKeyBase, IAsymmetricPublicKey, IAsymmetricKey
|
||||
{
|
||||
public override string Pem
|
||||
{
|
||||
get => base.Pem;
|
||||
init
|
||||
{
|
||||
base.Pem = value;
|
||||
RSA.ImportFromPem(value);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] Encrypt(byte[] data) => RSA.Encrypt(data, Padding);
|
||||
|
||||
public string Encrypt(string data) => RSA.Encrypt(data.ToBytes(), Padding).ToBase64String();
|
||||
|
||||
public bool Verify(string data, string signature) => Encrypt(data) == signature;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user