-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathCrypto.cs
133 lines (118 loc) · 4.88 KB
/
Crypto.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
using System;
using System.Text;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.DataProtection;
using System.IO;
using System.Security.Cryptography.X509Certificates;
namespace CLARiNET
{
class Crypto
{
public static string Protect(string stringToEncrypt)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return Convert.ToBase64String(
ProtectedData.Protect(
Encoding.UTF8.GetBytes(stringToEncrypt)
, null
, DataProtectionScope.CurrentUser));
}
else
{
return Convert.ToBase64String(
ProtectMac(stringToEncrypt)
);
}
}
public static string Unprotect(string encryptedString)
{
if (String.IsNullOrEmpty(encryptedString))
{
return "";
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return Encoding.UTF8.GetString(
ProtectedData.Unprotect(
Convert.FromBase64String(encryptedString)
, null
, DataProtectionScope.CurrentUser));
}
else
{
return Encoding.UTF8.GetString(
UnProtectMac(Convert.FromBase64String(encryptedString)));
}
}
// Credit: Oleg Batashov
// https://simplecodesoftware.com/articles/how-to-encrypt-data-on-macos-without-dpapi
private static IDataProtector MacEncryption()
{
IServiceCollection serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
IDataProtector dataProtector = serviceCollection
.BuildServiceProvider()
.GetDataProtector(purpose: "MacOsEncryption");
return dataProtector;
}
private static byte[] ProtectMac(string stringToEncrypt)
{
return MacEncryption().Protect(Encoding.UTF8.GetBytes(stringToEncrypt));
}
private static byte[] UnProtectMac(byte[] encryptedBytes)
{
return MacEncryption().Unprotect(encryptedBytes);
}
private static void ConfigureServices(IServiceCollection serviceCollection)
{
X509Certificate2 cert = SetupDataProtectionCertificate();
serviceCollection.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory))
.SetApplicationName("CLARiNET")
.ProtectKeysWithCertificate(cert);
}
static X509Certificate2 SetupDataProtectionCertificate()
{
string subjectName = "CN=CLARiNET Data Protection Certificate";
string subjectNameFind = subjectName.Substring(3);
using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser, OpenFlags.ReadOnly))
{
X509Certificate2Collection certificateCollection = store.Certificates.Find(X509FindType.FindBySubjectName,
subjectNameFind,
// self-signed certificate won't pass X509 chain validation
validOnly: false);
if (certificateCollection.Count > 0)
{
return certificateCollection[0];
}
X509Certificate2 certificate = CreateSelfSignedDataProtectionCertificate(subjectName);
InstallCertificateAsNonExportable(certificate);
return certificate;
}
}
static X509Certificate2 CreateSelfSignedDataProtectionCertificate(string subjectName)
{
using (RSA rsa = RSA.Create(2048))
{
CertificateRequest request = new CertificateRequest(subjectName, rsa, HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1);
X509Certificate2 cert = request.CreateSelfSigned(DateTimeOffset.UtcNow.AddMinutes(-1), DateTimeOffset.UtcNow.AddYears(50));
return cert;
}
}
static void InstallCertificateAsNonExportable(X509Certificate2 cert)
{
byte[] rawData = cert.Export(X509ContentType.Pkcs12, password: "CLARiNET" );
X509Certificate2 certPersistKey = new X509Certificate2(rawData, "CLARiNET", X509KeyStorageFlags.PersistKeySet);
using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser))
{
store.Open(OpenFlags.MaxAllowed | OpenFlags.ReadWrite);
store.Add(certPersistKey);
store.Close();
}
}
}
}