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; }
PrivateKeyTokenDescriptor? TokenDescriptor { get; init; }
byte[] Decrypt(byte[] data);
string Decrypt(string data);
SigningCredentials CreateSigningCredentials(string algorithm = SecurityAlgorithms.RsaSha256, string? digest = null);
}
}

View File

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

View File

@ -17,7 +17,7 @@ namespace DigitalData.Core.Abstractions.Security
/// <summary>
/// Defines the compression algorithm that will be used to compress the JWT token payload.
/// </summary>
public string CompressionAlgorithm { get; set; }
public string CompressionAlgorithm { get; set; }
/// <summary>
/// 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
{
@ -25,5 +28,12 @@
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);
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>
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()
{
@ -52,7 +52,7 @@ namespace DigitalData.Core.Security.Config
if (!Directory.Exists(PemDirectory))
Directory.CreateDirectory(PemDirectory);
foreach (var decryptor in PrivateKeys)
foreach (var decryptor in Decryptors)
{
// set default path
if (decryptor.IsPemNull)

View File

@ -8,12 +8,12 @@ namespace DigitalData.Core.Security
{
public class Cryptograph : RSAFactory<CryptographParams>, ICryptograph, IAsymmetricKeyFactory
{
public IEnumerable<IAsymmetricPrivateKey> PrivateKeys { get; }
public IEnumerable<IAsymmetricDecryptor> Decryptors { get; }
/// <summary>
/// It is a separate decryptor for permanently stored encrypted data. It is assigned to the first Default decryptor by default.
/// </summary>
public IAsymmetricPrivateKey VaultPrivateKey { get; }
public IAsymmetricDecryptor VaultDecryptor { get; }
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"));
if (!_params.PrivateKeys.Any())
if (!_params.Decryptors.Any())
throw new InvalidOperationException(
"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. " +
"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 DigitalData.Core.Abstractions.Security;
using DigitalData.Core.Security.Config;
using Microsoft.IdentityModel.Tokens;
namespace DigitalData.Core.Security
@ -8,13 +7,9 @@ namespace DigitalData.Core.Security
internal static class Extension
{
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 string BytesToString(this byte[] bytes) => System.Text.Encoding.UTF8.GetString(bytes);
/// <summary>
/// Converts a <see cref="DateTime"/> to a formatted string based on the specified format string.
/// <br />

View File

@ -35,14 +35,14 @@ namespace DigitalData.Core.Security
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}'.");
return CreateToken(subject: subject, key: (RSAPrivateKey)key);
}
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}'.");
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)
{
_pem = pem;