using System; using System.IO; using System.Security.Cryptography; using Microsoft.Extensions.Configuration; namespace SNote.Server.Security; public class RsaKeyManager { private readonly string _publicKeyPath; private readonly string _privateKeyPath; private RSA? _privateKeyRsa; private RSA? _publicKeyRsa; private string _publicKeyPem = string.Empty; private string _privateKeyPem = string.Empty; public RsaKeyManager(IConfiguration configuration) { _publicKeyPath = Path.Combine(AppContext.BaseDirectory, "snote-public.pem"); _privateKeyPath = Path.Combine(AppContext.BaseDirectory, "snote-private.pem"); var configPublicKey = configuration["Sync:PublicKey"]; var configPrivateKey = configuration["Sync:PrivateKey"]; if (!string.IsNullOrEmpty(configPublicKey) && !string.IsNullOrEmpty(configPrivateKey)) { _publicKeyPem = configPublicKey; _privateKeyPem = configPrivateKey; InitializeKeys(); } else { LoadOrGenerateKeys(); } } private void InitializeKeys() { try { _publicKeyRsa = RSA.Create(); _publicKeyRsa.ImportFromPem(_publicKeyPem); _privateKeyRsa = RSA.Create(); _privateKeyRsa.ImportFromPem(_privateKeyPem); } catch (Exception ex) { Console.WriteLine($"[RsaKeyManager] Error initializing configured keys: {ex.Message}"); throw; } } private void LoadOrGenerateKeys() { if (File.Exists(_privateKeyPath) && File.Exists(_publicKeyPath)) { try { _publicKeyPem = File.ReadAllText(_publicKeyPath); _privateKeyPem = File.ReadAllText(_privateKeyPath); InitializeKeys(); Console.WriteLine("[RsaKeyManager] Loaded existing RSA keys from disk."); return; } catch (Exception ex) { Console.WriteLine($"[RsaKeyManager] Error loading RSA keys from disk: {ex.Message}. Re-generating."); } } // Generate new keypair Console.WriteLine("[RsaKeyManager] Generating new secure 2048-bit RSA keypair..."); using var rsa = RSA.Create(2048); _publicKeyPem = rsa.ExportSubjectPublicKeyInfoPem(); _privateKeyPem = rsa.ExportPkcs8PrivateKeyPem(); File.WriteAllText(_publicKeyPath, _publicKeyPem); File.WriteAllText(_privateKeyPath, _privateKeyPem); InitializeKeys(); Console.WriteLine("[RsaKeyManager] Secure RSA keypair generated and saved to disk."); } public RSA GetPrivateKey() { if (_privateKeyRsa == null) throw new InvalidOperationException("Private key is not loaded."); return _privateKeyRsa; } public RSA GetPublicKey() { if (_publicKeyRsa == null) throw new InvalidOperationException("Public key is not loaded."); return _publicKeyRsa; } public string GetPublicKeyPem() { return _publicKeyPem; } public string GetPrivateKeyPem() { return _privateKeyPem; } }