Implemented with Antigravity.
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace SNote.Server.Security;
|
||||
|
||||
public class CertificateManager
|
||||
{
|
||||
private readonly string _certPath;
|
||||
private readonly string _certPassword = "snote-password";
|
||||
private X509Certificate2? _certificate;
|
||||
|
||||
public CertificateManager(IConfiguration configuration)
|
||||
{
|
||||
var path = configuration["SharedCertificatePath"];
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
path = Path.Combine(AppContext.BaseDirectory, "snote-shared.pfx");
|
||||
}
|
||||
_certPath = path;
|
||||
}
|
||||
|
||||
public X509Certificate2 GetCertificate()
|
||||
{
|
||||
if (_certificate != null) return _certificate;
|
||||
|
||||
if (File.Exists(_certPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
var bytes = File.ReadAllBytes(_certPath);
|
||||
// EphemeralKeySet is standard and cross-platform for loading certificates from memory
|
||||
_certificate = new X509Certificate2(bytes, _certPassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.EphemeralKeySet);
|
||||
return _certificate;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error loading certificate at {_certPath}: {ex.Message}. Re-generating.");
|
||||
}
|
||||
}
|
||||
|
||||
// Generate new self-signed certificate
|
||||
_certificate = GenerateCertificate();
|
||||
return _certificate;
|
||||
}
|
||||
|
||||
private X509Certificate2 GenerateCertificate()
|
||||
{
|
||||
Console.WriteLine($"Generating a new shared network certificate at {_certPath}...");
|
||||
using var rsa = RSA.Create(2048);
|
||||
var req = new CertificateRequest("cn=SNoteSharedNetwork", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
|
||||
req.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.KeyEncipherment, true));
|
||||
|
||||
var selfSigned = req.CreateSelfSigned(DateTimeOffset.UtcNow.AddDays(-1), DateTimeOffset.UtcNow.AddYears(20));
|
||||
|
||||
var pfxBytes = selfSigned.Export(X509ContentType.Pfx, _certPassword);
|
||||
|
||||
var dir = Path.GetDirectoryName(_certPath);
|
||||
if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
}
|
||||
|
||||
File.WriteAllBytes(_certPath, pfxBytes);
|
||||
|
||||
// Reload it to ensure it contains exportable keys and correct storage flags
|
||||
return new X509Certificate2(pfxBytes, _certPassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.EphemeralKeySet);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user