refactor(Privatekey): Die Klasse decryptor wurde erstellt und die Verschlüsselungsfunktionen für eine einfache und saubere Konfiguration dorthin verschoben.

This commit is contained in:
Developer 02 2025-01-08 18:45:36 +01:00
parent 608d266d1c
commit 9f0facc487
11 changed files with 43 additions and 30 deletions

View File

@ -0,0 +1,7 @@
namespace DigitalData.Core.Abstractions.Security
{
public interface IAsymmetricDecryptor : IAsymmetricPrivateKey
{
byte[] Decrypt(byte[] data);
}
}

View File

@ -9,11 +9,7 @@ namespace DigitalData.Core.Abstractions.Security
IAsymmetricPublicKey PublicKey { get; } IAsymmetricPublicKey PublicKey { get; }
PrivateKeyTokenDescriptor? TokenDescriptor { get; init; } PrivateKeyTokenDescriptor? TokenDescriptor { get; init; }
byte[] Decrypt(byte[] data);
string Decrypt(string data);
SigningCredentials CreateSigningCredentials(string algorithm = SecurityAlgorithms.RsaSha256, string? digest = null); SigningCredentials CreateSigningCredentials(string algorithm = SecurityAlgorithms.RsaSha256, string? digest = null);
} }
} }

View File

@ -2,9 +2,9 @@
{ {
public interface ICryptograph : IAsymmetricKeyFactory public interface ICryptograph : IAsymmetricKeyFactory
{ {
IEnumerable<IAsymmetricPrivateKey> PrivateKeys { get; } IEnumerable<IAsymmetricDecryptor> Decryptors { get; }
IAsymmetricPrivateKey VaultPrivateKey { get; } IAsymmetricDecryptor VaultDecryptor { get; }
IEnumerable<IAsymmetricPublicKey> PublicKeys { get; } IEnumerable<IAsymmetricPublicKey> PublicKeys { get; }
} }

View File

@ -17,7 +17,7 @@ namespace DigitalData.Core.Abstractions.Security
/// <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.

View File

@ -1,4 +1,7 @@
namespace DigitalData.Core.Abstractions.Security using System.Security.Cryptography;
using System.Text;
namespace DigitalData.Core.Abstractions.Security
{ {
public static class SecurityExtensions public static class SecurityExtensions
{ {
@ -25,5 +28,12 @@
public static bool TryMatch<TUniqueSecurityContext>(this IEnumerable<TUniqueSecurityContext> contextes, IUniqueSecurityContext lookupContext, out TUniqueSecurityContext context) where TUniqueSecurityContext : IUniqueSecurityContext public static bool TryMatch<TUniqueSecurityContext>(this IEnumerable<TUniqueSecurityContext> contextes, IUniqueSecurityContext lookupContext, out TUniqueSecurityContext context) where TUniqueSecurityContext : IUniqueSecurityContext
=> contextes.TryGet(lookupContext.Issuer, lookupContext.Audience, out context); => contextes.TryGet(lookupContext.Issuer, lookupContext.Audience, out context);
internal static byte[] Base64ToByte(this string base64String) => Convert.FromBase64String(base64String);
internal static string BytesToString(this byte[] bytes) => Encoding.UTF8.GetString(bytes);
public static string Decrypt(this IAsymmetricDecryptor decryptor, string data) => decryptor
.Decrypt(data.Base64ToByte()).BytesToString();
} }
} }

View File

@ -39,9 +39,9 @@ namespace DigitalData.Core.Security.Config
/// </summary> /// </summary>
public string DateTagFormat { get; init; } = "MM//2"; public string DateTagFormat { get; init; } = "MM//2";
public IEnumerable<RSAPrivateKey> PrivateKeys { get; init; } = new List<RSAPrivateKey>(); public IEnumerable<RSADecryptor> Decryptors { get; init; } = new List<RSADecryptor>();
public RSAPrivateKey? VaultPrivateKey { get; init; } public RSADecryptor? VaultDecryptor { get; init; }
public CryptographParams() public CryptographParams()
{ {
@ -52,7 +52,7 @@ namespace DigitalData.Core.Security.Config
if (!Directory.Exists(PemDirectory)) if (!Directory.Exists(PemDirectory))
Directory.CreateDirectory(PemDirectory); Directory.CreateDirectory(PemDirectory);
foreach (var decryptor in PrivateKeys) foreach (var decryptor in Decryptors)
{ {
// set default path // set default path
if (decryptor.IsPemNull) if (decryptor.IsPemNull)

View File

@ -8,12 +8,12 @@ namespace DigitalData.Core.Security
{ {
public class Cryptograph : RSAFactory<CryptographParams>, ICryptograph, IAsymmetricKeyFactory public class Cryptograph : RSAFactory<CryptographParams>, ICryptograph, IAsymmetricKeyFactory
{ {
public IEnumerable<IAsymmetricPrivateKey> PrivateKeys { get; } public IEnumerable<IAsymmetricDecryptor> Decryptors { get; }
/// <summary> /// <summary>
/// It is a separate decryptor for permanently stored encrypted data. It is assigned to the first Default decryptor by default. /// It is a separate decryptor for permanently stored encrypted data. It is assigned to the first Default decryptor by default.
/// </summary> /// </summary>
public IAsymmetricPrivateKey VaultPrivateKey { get; } public IAsymmetricDecryptor VaultDecryptor { get; }
private readonly Lazy<IEnumerable<IAsymmetricPublicKey>> _lazyPublicKeys; private readonly Lazy<IEnumerable<IAsymmetricPublicKey>> _lazyPublicKeys;
@ -25,18 +25,18 @@ namespace DigitalData.Core.Security
{ {
logger?.LogInformation("Core.Secrets version: {Version}, Created on: {CreationDate}.", Secrets.Version, Secrets.CreationDate.ToString("dd.MM.yyyy")); logger?.LogInformation("Core.Secrets version: {Version}, Created on: {CreationDate}.", Secrets.Version, Secrets.CreationDate.ToString("dd.MM.yyyy"));
if (!_params.PrivateKeys.Any()) if (!_params.Decryptors.Any())
throw new InvalidOperationException( throw new InvalidOperationException(
"Any decryptor is not found. Ensure that at least one decryptor is configured in the provided parameters. " + "Any decryptor is not found. Ensure that at least one decryptor is configured in the provided parameters. " +
"This issue typically arises if the configuration for decryptors is incomplete or missing. " + "This issue typically arises if the configuration for decryptors is incomplete or missing. " +
"Check the 'Decryptors' collection in the configuration and verify that it contains valid entries." "Check the 'Decryptors' collection in the configuration and verify that it contains valid entries."
); );
PrivateKeys = _params.PrivateKeys; Decryptors = _params.Decryptors;
VaultPrivateKey = _params.VaultPrivateKey ?? PrivateKeys.First(); VaultDecryptor = _params.VaultDecryptor ?? Decryptors.First();
_lazyPublicKeys = new(PrivateKeys.Select(decryptor => decryptor.PublicKey)); _lazyPublicKeys = new(Decryptors.Select(decryptor => decryptor.PublicKey));
} }
} }
} }

View File

@ -1,6 +1,5 @@
using AutoMapper; using AutoMapper;
using DigitalData.Core.Abstractions.Security; using DigitalData.Core.Abstractions.Security;
using DigitalData.Core.Security.Config;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
namespace DigitalData.Core.Security namespace DigitalData.Core.Security
@ -8,13 +7,9 @@ namespace DigitalData.Core.Security
internal static class Extension internal static class Extension
{ {
internal static string ToBase64String(this byte[] bytes) => Convert.ToBase64String(bytes); internal static string ToBase64String(this byte[] bytes) => Convert.ToBase64String(bytes);
internal static byte[] Base64ToByte(this string base64String) => Convert.FromBase64String(base64String);
internal static byte[] ToBytes(this string str) => System.Text.Encoding.UTF8.GetBytes(str); internal static byte[] ToBytes(this string str) => System.Text.Encoding.UTF8.GetBytes(str);
internal static string BytesToString(this byte[] bytes) => System.Text.Encoding.UTF8.GetString(bytes);
/// <summary> /// <summary>
/// Converts a <see cref="DateTime"/> to a formatted string based on the specified format string. /// Converts a <see cref="DateTime"/> to a formatted string based on the specified format string.
/// <br /> /// <br />

View File

@ -35,14 +35,14 @@ namespace DigitalData.Core.Security
public SecurityToken CreateToken(TPrincipal subject, string issuer, string audience) public SecurityToken CreateToken(TPrincipal subject, string issuer, string audience)
{ {
var key = _cryptograph.PrivateKeys?.Get(issuer: issuer, audience: audience) var key = _cryptograph.Decryptors?.Get(issuer: issuer, audience: audience)
?? throw new InvalidOperationException($"No or multiple token description found for issuer '{issuer}' and audience '{audience}'."); ?? throw new InvalidOperationException($"No or multiple token description found for issuer '{issuer}' and audience '{audience}'.");
return CreateToken(subject: subject, key: (RSAPrivateKey)key); return CreateToken(subject: subject, key: (RSAPrivateKey)key);
} }
public SecurityToken CreateToken(TPrincipal subject, string apiRoute) public SecurityToken CreateToken(TPrincipal subject, string apiRoute)
{ {
var key = _cryptograph.PrivateKeys.SingleOrDefault(key => ((RSAPrivateKey)key).TokenDescriptor?.ApiRoute == apiRoute) var key = _cryptograph.Decryptors.SingleOrDefault(key => ((RSAPrivateKey)key).TokenDescriptor?.ApiRoute == apiRoute)
?? throw new InvalidOperationException($"No or multiple token description found for api route '{apiRoute}'."); ?? throw new InvalidOperationException($"No or multiple token description found for api route '{apiRoute}'.");
return CreateToken(subject: subject, key: (RSAPrivateKey)key); return CreateToken(subject: subject, key: (RSAPrivateKey)key);

View File

@ -0,0 +1,9 @@
using DigitalData.Core.Abstractions.Security;
namespace DigitalData.Core.Security.RSAKey
{
public class RSADecryptor : RSAPrivateKey, IAsymmetricDecryptor
{
public byte[] Decrypt(byte[] data) => RSA.Decrypt(data, Padding);
}
}

View File

@ -54,10 +54,6 @@ namespace DigitalData.Core.Security.RSAKey
}); });
} }
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) internal void SetPem(string pem)
{ {
_pem = pem; _pem = pem;