refactor(RSATokenDescriptor): Die Klasse RSA Token Descriptor wurde erstellt und die Funktionen wurden dorthin verschoben, um eine einfache und saubere Konfiguration zu ermöglichen.

This commit is contained in:
Developer 02 2025-01-09 17:59:13 +01:00
parent 2557525f06
commit 87ad45f42a
10 changed files with 48 additions and 55 deletions

View File

@ -10,7 +10,5 @@ namespace DigitalData.Core.Abstractions.Security
public new string Issuer { get; init; } public new string Issuer { get; init; }
public new string Audience { get; init; } public new string Audience { get; init; }
public SecurityKey SecurityKey { get; }
} }
} }

View File

@ -7,9 +7,5 @@ namespace DigitalData.Core.Abstractions.Security
public bool IsEncrypted { get; init; } public bool IsEncrypted { get; init; }
IAsymmetricPublicKey PublicKey { get; } IAsymmetricPublicKey PublicKey { get; }
PrivateKeyTokenDescriptor? TokenDescriptor { get; init; }
SigningCredentials CreateSigningCredentials(string algorithm = SecurityAlgorithms.RsaSha256, string? digest = null);
} }
} }

View File

@ -0,0 +1,13 @@
using Microsoft.IdentityModel.Tokens;
namespace DigitalData.Core.Abstractions.Security
{
public interface IAsymmetricTokenDescriptor : IAsymmetricPrivateKey, IUniqueSecurityContext
{
string? ApiRoute { get; }
SecurityKey SecurityKey { get; }
SigningCredentials SigningCredentials { get; }
}
}

View File

@ -41,6 +41,8 @@ namespace DigitalData.Core.Security.Config
public IEnumerable<RSADecryptor> Decryptors { get; init; } = new List<RSADecryptor>(); public IEnumerable<RSADecryptor> Decryptors { get; init; } = new List<RSADecryptor>();
public IEnumerable<RSATokenDescriptor> TokenDescriptors { get; init; } = new List<RSATokenDescriptor>();
public RSADecryptor? VaultDecryptor { get; init; } public RSADecryptor? VaultDecryptor { get; init; }
public CryptographParams() public CryptographParams()

View File

@ -8,7 +8,7 @@ namespace DigitalData.Core.Security.Config
{ {
public MappingProfile() public MappingProfile()
{ {
CreateMap<PrivateKeyTokenDescriptor, SecurityTokenDescriptor>(); CreateMap<IAsymmetricTokenDescriptor, SecurityTokenDescriptor>();
} }
} }
} }

View File

@ -19,7 +19,7 @@ namespace DigitalData.Core.Security
public IEnumerable<IAsymmetricEncryptor> Encryptors => _lazyEncryptors.Value; public IEnumerable<IAsymmetricEncryptor> Encryptors => _lazyEncryptors.Value;
public IEnumerable<PrivateKeyTokenDescriptor> TokenDescriptions { get; init; } = new List<PrivateKeyTokenDescriptor>(); public IEnumerable<IAsymmetricTokenDescriptor> TokenDescriptors { get; init; } = new List<IAsymmetricTokenDescriptor>();
public Cryptograph(IOptions<CryptographParams> options, ILogger<Cryptograph>? logger = null) : base(options) public Cryptograph(IOptions<CryptographParams> options, ILogger<Cryptograph>? logger = null) : base(options)
{ {

View File

@ -83,7 +83,7 @@ namespace DigitalData.Core.Security
/// <param name="description">The <see cref="RSATokenDescriptor"/> instance to be mapped.</param> /// <param name="description">The <see cref="RSATokenDescriptor"/> instance to be mapped.</param>
/// <returns>A <see cref="SecurityTokenDescriptor"/> instance populated with the mapped values.</returns> /// <returns>A <see cref="SecurityTokenDescriptor"/> instance populated with the mapped values.</returns>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="mapper"/> or <paramref name="description"/> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">Thrown if <paramref name="mapper"/> or <paramref name="description"/> is <c>null</c>.</exception>
internal static SecurityTokenDescriptor Map(this IMapper mapper, PrivateKeyTokenDescriptor description) internal static SecurityTokenDescriptor Map(this IMapper mapper, IAsymmetricTokenDescriptor description)
=> mapper.Map(description, new SecurityTokenDescriptor()); => mapper.Map(description, new SecurityTokenDescriptor());
} }
} }

View File

@ -1,6 +1,5 @@
using DigitalData.Core.Abstractions.Security; using DigitalData.Core.Abstractions.Security;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using System.Reflection;
using System.Security.Cryptography; using System.Security.Cryptography;
namespace DigitalData.Core.Security.RSAKey namespace DigitalData.Core.Security.RSAKey
@ -14,15 +13,11 @@ namespace DigitalData.Core.Security.RSAKey
public string Issuer { get; init; } = string.Empty; public string Issuer { get; init; } = string.Empty;
public string Audience { get; init; } = string.Empty; public string Audience { get; init; } = string.Empty;
private readonly Lazy<RsaSecurityKey> _lazyRsaSecurityKey;
public SecurityKey SecurityKey => _lazyRsaSecurityKey.Value;
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
internal RSAKeyBase() 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. #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
} }

View File

@ -28,29 +28,12 @@ namespace DigitalData.Core.Security.RSAKey
public IAsymmetricPublicKey PublicKey => _lazyPublicKey.Value; public IAsymmetricPublicKey PublicKey => _lazyPublicKey.Value;
private PrivateKeyTokenDescriptor? _tokenDescriptor;
private readonly Lazy<PrivateKeyTokenDescriptor?> _descriptorInitiator;
public PrivateKeyTokenDescriptor? TokenDescriptor { get => _descriptorInitiator.Value; init => _tokenDescriptor = value; }
public RSAPrivateKey() public RSAPrivateKey()
{ {
_lazyPublicKey = new(() => new RSAPublicKey() _lazyPublicKey = new(() => new RSAPublicKey()
{ {
Content = RSA.ExportRSAPublicKeyPem() Content = RSA.ExportRSAPublicKeyPem()
}); });
_descriptorInitiator = new(() =>
{
if(_tokenDescriptor is not null)
{
_tokenDescriptor.Issuer = Issuer;
_tokenDescriptor.Audience = Audience;
_tokenDescriptor.SigningCredentials = CreateSigningCredentials();
}
return _tokenDescriptor;
});
} }
internal void SetPem(string pem) internal void SetPem(string pem)
@ -71,8 +54,5 @@ namespace DigitalData.Core.Security.RSAKey
} }
private InvalidOperationException PemIsNullException => new($"Content is null or empty. Issuer: {Issuer}, Audience: {Audience}."); private InvalidOperationException PemIsNullException => new($"Content is null or empty. Issuer: {Issuer}, Audience: {Audience}.");
public SigningCredentials CreateSigningCredentials(string algorithm = SecurityAlgorithms.RsaSha256, string? digest = null)
=> digest is null ? new(SecurityKey, algorithm) : new(SecurityKey, algorithm, digest);
} }
} }

View File

@ -1,24 +1,21 @@
using Microsoft.IdentityModel.Tokens; using DigitalData.Core.Abstractions.Security;
using Microsoft.IdentityModel.Tokens;
using System.Security.Cryptography;
namespace DigitalData.Core.Abstractions.Security namespace DigitalData.Core.Security.RSAKey
{ {
/// <summary> /// <summary>
/// Contains some information which used to create a security token. Designed to abstract <see cref="SecurityTokenDescriptor"/> /// Contains some information which used to create a security token. Designed to abstract <see cref="SecurityTokenDescriptor"/>
/// </summary> /// </summary>
public class PrivateKeyTokenDescriptor : IUniqueSecurityContext public class RSATokenDescriptor : RSAPrivateKey, IAsymmetricTokenDescriptor
{ {
public string? ApiRoute { get; init; } public string? ApiRoute { get; init; }
/// <summary> #region SecurityTokenDescriptor Map
/// Gets or sets the value of the 'audience' claim.
/// </summary>
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
public string Audience { get; set; }
/// <summary> /// <summary>
/// Defines the compression algorithm that will be used to compress the JWT token payload. /// Defines the compression algorithm that will be used to compress the JWT token payload.
/// </summary> /// </summary>
public string CompressionAlgorithm { get; set; } public string CompressionAlgorithm { get; set; }
/// <summary> /// <summary>
/// Gets or sets the <see cref="EncryptingCredentials"/> used to create a encrypted security token. /// Gets or sets the <see cref="EncryptingCredentials"/> used to create a encrypted security token.
@ -30,11 +27,6 @@ namespace DigitalData.Core.Abstractions.Security
/// </summary> /// </summary>
public DateTime? Expires { get; set; } public DateTime? Expires { get; set; }
/// <summary>
/// Gets or sets the issuer of this <see cref="PrivateKeyTokenDescriptor"/>.
/// </summary>
public string Issuer { get; set; }
/// <summary> /// <summary>
/// Gets or sets the time the security token was issued. This value should be in UTC. /// Gets or sets the time the security token was issued. This value should be in UTC.
/// </summary> /// </summary>
@ -76,19 +68,36 @@ namespace DigitalData.Core.Abstractions.Security
/// <summary> /// <summary>
/// Gets or sets the <see cref="SigningCredentials"/> used to create a security token. /// Gets or sets the <see cref="SigningCredentials"/> used to create a security token.
/// </summary> /// </summary>
public SigningCredentials SigningCredentials { get; set; } public SigningCredentials SigningCredentials => _lazySigningCredentials.Value;
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. #endregion SecurityTokenDescriptor
private readonly Lazy<RsaSecurityKey> _lazyRsaSecurityKey;
public SecurityKey SecurityKey => _lazyRsaSecurityKey.Value;
private readonly Lazy<SigningCredentials> _lazySigningCredentials;
/// <summary> /// <summary>
/// Specifies the signature algorithm to be applied to the <see cref="SigningCredentials"/>. /// Specifies the signature algorithm to be applied to the <see cref="SigningCredentials"/>.
/// Default is <see cref="SecurityAlgorithms.RsaSha256"/>. /// Default is <see cref="SecurityAlgorithms.RsaSha256"/>.
/// </summary> /// </summary>
public string SigningAlgorithm { get; internal set; } = SecurityAlgorithms.RsaSha256; public string SigningAlgorithm { get; init; } = SecurityAlgorithms.RsaSha256;
/// <summary> /// <summary>
/// Optionally specifies the digest algorithm to be applied during the signing process for the <see cref="SigningCredentials"/>. /// Optionally specifies the digest algorithm to be applied during the signing process for the <see cref="SigningCredentials"/>.
/// If not provided, the default algorithm is used. /// If not provided, the default algorithm is used.
/// </summary> /// </summary>
public string? SigningDigest { get; init; } public string? SigningDigest { get; init; }
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
public RSATokenDescriptor()
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
{
_lazyRsaSecurityKey = new(() => new RsaSecurityKey(RSA));
_lazySigningCredentials = new(() => SigningDigest is null
? new(SecurityKey, SigningAlgorithm)
: new(SecurityKey, SigningAlgorithm, SigningDigest));
}
} }
} }