Compare commits
15 Commits
0804ea1418
...
4c379c2d4d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c379c2d4d | ||
|
|
fee43c00ca | ||
|
|
ee3060158e | ||
|
|
4e615d7e39 | ||
|
|
d1fea581d7 | ||
|
|
26a68cd477 | ||
|
|
eccf2b32ce | ||
|
|
6ff0d0a876 | ||
|
|
0bb779b7b6 | ||
|
|
51ebf3fa67 | ||
|
|
8cc6fd95f7 | ||
|
|
c5b422921b | ||
|
|
7b571e4d86 | ||
|
|
c39b554165 | ||
|
|
489ca67203 |
12
DigitalData.Core.Abstractions/Security/ICryptFactory.cs
Normal file
12
DigitalData.Core.Abstractions/Security/ICryptFactory.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DigitalData.Core.Abstractions.Security
|
||||
{
|
||||
public interface ICryptFactory
|
||||
{
|
||||
}
|
||||
}
|
||||
11
DigitalData.Core.Abstractions/Security/IRSACryptographer.cs
Normal file
11
DigitalData.Core.Abstractions/Security/IRSACryptographer.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace DigitalData.Core.Abstractions.Security
|
||||
{
|
||||
public interface IRSACryptographer
|
||||
{
|
||||
public string Pem { get; init; }
|
||||
|
||||
public RSAEncryptionPadding Padding { get; init; }
|
||||
}
|
||||
}
|
||||
13
DigitalData.Core.Abstractions/Security/IRSADecryptor.cs
Normal file
13
DigitalData.Core.Abstractions/Security/IRSADecryptor.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace DigitalData.Core.Abstractions.Security
|
||||
{
|
||||
public interface IRSADecryptor : IRSACryptographer
|
||||
{
|
||||
public string? Password { get; init; }
|
||||
|
||||
public IRSAEncryptor Encryptor { get; }
|
||||
|
||||
public byte[] Decrypt(byte[] data);
|
||||
|
||||
public string Decrypt(string data);
|
||||
}
|
||||
}
|
||||
11
DigitalData.Core.Abstractions/Security/IRSAEncryptor.cs
Normal file
11
DigitalData.Core.Abstractions/Security/IRSAEncryptor.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace DigitalData.Core.Abstractions.Security
|
||||
{
|
||||
public interface IRSAEncryptor : IRSACryptographer
|
||||
{
|
||||
public byte[] Encrypt(byte[] data);
|
||||
|
||||
public string Encrypt(string data);
|
||||
|
||||
public bool Verify(string data, string signature) => Encrypt(data) == signature;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DigitalData.Core.Abstractions\DigitalData.Core.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace DigitalData.Core.Security
|
||||
namespace DigitalData.Core.Security.Extensions
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
21
DigitalData.Core.Security.Extensions/RSAExtensions.cs
Normal file
21
DigitalData.Core.Security.Extensions/RSAExtensions.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using DigitalData.Core.Abstractions.Security;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace DigitalData.Core.Security.Extensions
|
||||
{
|
||||
public static class RSAExtensions
|
||||
{
|
||||
public static RSA ToRSA(this string pem)
|
||||
{
|
||||
var rsa = RSA.Create();
|
||||
rsa.ImportFromPem(pem);
|
||||
return rsa;
|
||||
}
|
||||
|
||||
public static bool TryGetEncryptor(this IDictionary<string, IRSAEncryptor> pairs, string issuer, string audience, out IRSAEncryptor? encryptor)
|
||||
=> pairs.TryGetValue($"{issuer}:{audience}", out encryptor);
|
||||
|
||||
public static IRSAEncryptor? GetEncryptor(this IDictionary<string, IRSAEncryptor> pairs, string issuer, string audience)
|
||||
=> pairs.TryGetEncryptor(issuer: issuer, audience: audience, out var encryptor) ? encryptor : null;
|
||||
}
|
||||
}
|
||||
11
DigitalData.Core.Security/CryptFactory.cs
Normal file
11
DigitalData.Core.Security/CryptFactory.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using DigitalData.Core.Abstractions.Security;
|
||||
|
||||
namespace DigitalData.Core.Security
|
||||
{
|
||||
public class CryptFactory : ICryptFactory
|
||||
{
|
||||
private static readonly Lazy<ICryptFactory> LazyStaticCryptFactory = new (() => new CryptFactory());
|
||||
|
||||
public ICryptFactory Static = LazyStaticCryptFactory.Value;
|
||||
}
|
||||
}
|
||||
@@ -6,4 +6,9 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DigitalData.Core.Abstractions\DigitalData.Core.Abstractions.csproj" />
|
||||
<ProjectReference Include="..\DigitalData.Core.Security.Extensions\DigitalData.Core.Security.Extensions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,21 +1,16 @@
|
||||
using System.Security.Cryptography;
|
||||
using DigitalData.Core.Abstractions.Security;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace DigitalData.Core.Security
|
||||
{
|
||||
public class RSACryptographer
|
||||
public class RSACryptographer : IRSACryptographer
|
||||
{
|
||||
internal RSACryptographer() { }
|
||||
public required virtual string Pem { get; init; }
|
||||
|
||||
public required string Pem
|
||||
{
|
||||
init
|
||||
{
|
||||
_rsa.ImportFromPem(value);
|
||||
}
|
||||
}
|
||||
|
||||
public required RSAEncryptionPadding Padding { get; init; }
|
||||
public RSAEncryptionPadding Padding { get; init; } = RSAEncryptionPadding.OaepSHA256;
|
||||
|
||||
protected readonly RSA _rsa = RSA.Create();
|
||||
|
||||
internal RSACryptographer() { }
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,45 @@
|
||||
using System.Security.Cryptography;
|
||||
using DigitalData.Core.Abstractions.Security;
|
||||
using DigitalData.Core.Security.Extensions;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace DigitalData.Core.Security
|
||||
{
|
||||
public class RSADecryptor : RSACryptographer
|
||||
public class RSADecryptor : RSACryptographer, IRSADecryptor, IRSACryptographer
|
||||
{
|
||||
public string PublicKeyPem => _rsa.ExportRSAPublicKeyPem();
|
||||
public string? Password { get; init; }
|
||||
|
||||
public RSAEncryptor Encryptor
|
||||
public bool IsEncrypted => Password is not null;
|
||||
|
||||
public IRSAEncryptor Encryptor
|
||||
{
|
||||
get
|
||||
{
|
||||
return new ()
|
||||
return new RSAEncryptor()
|
||||
{
|
||||
Pem = PublicKeyPem,
|
||||
Pem = _rsa.ExportRSAPublicKeyPem(),
|
||||
Padding = Padding
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal RSADecryptor() { }
|
||||
|
||||
[OnDeserialized]
|
||||
private void OnDeserialized(StreamingContext context) => Init();
|
||||
|
||||
private IRSADecryptor Init()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Pem))
|
||||
throw new InvalidOperationException("Pem cannot be null or empty.");
|
||||
|
||||
if (Password is null)
|
||||
_rsa.ImportFromPem(Pem);
|
||||
else
|
||||
_rsa.ImportFromEncryptedPem(Pem, Password.AsSpan());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public byte[] Decrypt(byte[] data) => _rsa.Decrypt(data, Padding);
|
||||
|
||||
public string Decrypt(string data) => _rsa.Decrypt(data.Base64ToByte(), Padding).BytesToString();
|
||||
|
||||
@@ -1,7 +1,23 @@
|
||||
namespace DigitalData.Core.Security
|
||||
using DigitalData.Core.Abstractions.Security;
|
||||
using DigitalData.Core.Security.Extensions;
|
||||
|
||||
namespace DigitalData.Core.Security
|
||||
{
|
||||
public class RSAEncryptor : RSACryptographer
|
||||
public class RSAEncryptor : RSACryptographer, IRSAEncryptor, IRSACryptographer
|
||||
{
|
||||
public override required string Pem
|
||||
{
|
||||
get => base.Pem;
|
||||
init
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Pem))
|
||||
throw new InvalidOperationException("Pem cannot be null or empty.");
|
||||
|
||||
_rsa.ImportFromPem(base.Pem);
|
||||
base.Pem = value;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] Encrypt(byte[] data) => _rsa.Encrypt(data, Padding);
|
||||
|
||||
public string Encrypt(string data) => _rsa.Encrypt(data.Base64ToByte(), Padding).BytesToString();
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace DigitalData.Core.Security
|
||||
{
|
||||
public static class RSAExtensions
|
||||
{
|
||||
public static RSA ToRSA(this string pem)
|
||||
{
|
||||
var rsa = RSA.Create();
|
||||
rsa.ImportFromPem(pem);
|
||||
return rsa;
|
||||
}
|
||||
}
|
||||
}
|
||||
7
DigitalData.Core.Tests/Security/RSADecryptorTests.cs
Normal file
7
DigitalData.Core.Tests/Security/RSADecryptorTests.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace DigitalData.Core.Tests.Security
|
||||
{
|
||||
[TestFixture]
|
||||
public class RSADecryptorTests
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DigitalData.Core.Legacy.Tes
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DigitalData.Core.Legacy.Client", "DigitalData.Core.Legacy.Client\DigitalData.Core.Legacy.Client.csproj", "{E009A053-A9F4-48F2-984F-EF5C376A9B14}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DigitalData.Core.Security", "DigitalData.Core.Security\DigitalData.Core.Security.csproj", "{47D80C65-74A2-4EB8-96A5-D571A9108FB3}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DigitalData.Core.Security", "DigitalData.Core.Security\DigitalData.Core.Security.csproj", "{47D80C65-74A2-4EB8-96A5-D571A9108FB3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DigitalData.Core.Security.Extensions", "DigitalData.Core.Security.Extensions\DigitalData.Core.Security.Extensions.csproj", "{D740182D-82DA-480A-9F87-BFB4A8620A00}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@@ -68,6 +70,10 @@ Global
|
||||
{47D80C65-74A2-4EB8-96A5-D571A9108FB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{47D80C65-74A2-4EB8-96A5-D571A9108FB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{47D80C65-74A2-4EB8-96A5-D571A9108FB3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D740182D-82DA-480A-9F87-BFB4A8620A00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D740182D-82DA-480A-9F87-BFB4A8620A00}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D740182D-82DA-480A-9F87-BFB4A8620A00}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D740182D-82DA-480A-9F87-BFB4A8620A00}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
Reference in New Issue
Block a user