using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; namespace Tiku.Infrastructure.Security; public sealed class DataProtectionKeyRingOptions { public const string SectionName = "Security:DataProtection"; public string ApplicationName { get; set; } = "Tiku.Api"; public string CertificatePath { get; set; } = string.Empty; public string CertificatePassword { get; set; } = string.Empty; public static bool BeValid(DataProtectionKeyRingOptions options, bool requireCertificate) { return !string.IsNullOrWhiteSpace(options.ApplicationName) && (!requireCertificate || !string.IsNullOrWhiteSpace(options.CertificatePath)); } public X509Certificate2? LoadCertificate(bool requireCertificate) { if (string.IsNullOrWhiteSpace(CertificatePath)) { if (requireCertificate) { throw new InvalidOperationException( "Data Protection certificate is required outside Development. " + "Configure Security:DataProtection:CertificatePath or " + "TIKU_DATA_PROTECTION_CERTIFICATE_PATH."); } return null; } try { var certificate = X509CertificateLoader.LoadPkcs12FromFile( Path.GetFullPath(CertificatePath.Trim()), CertificatePassword, X509KeyStorageFlags.DefaultKeySet); if (!certificate.HasPrivateKey) { certificate.Dispose(); throw new InvalidOperationException( "Data Protection certificate must contain a private key."); } return certificate; } catch (InvalidOperationException) { throw; } catch (Exception exception) when ( exception is CryptographicException or IOException or UnauthorizedAccessException) { throw new InvalidOperationException( "Data Protection certificate could not be loaded from the configured PKCS#12 file.", exception); } } }