using System.Security.Cryptography.X509Certificates; using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Tokens; namespace FitConnect.Encryption; public class CertificateHelper { private readonly ILogger? _logger; public CertificateHelper(ILogger? logger = null) { _logger = logger; } internal bool ValidateCertificate(string keyJson, LogLevel logLevel) => ValidateCertificate(new JsonWebKey(keyJson), logLevel); internal bool ValidateCertificate(JsonWebKey key, LogLevel logLevel = LogLevel.Error) { var certificates = key.X5c.Select(s => new X509Certificate2(Convert.FromBase64String(s))) .ToList(); _logger?.LogTrace("Found {Count} certificate(s)", certificates.Count); var valid = certificates.Aggregate(true, (result, cert) => result && ValidateCertificate(cert, out var _, logLevel) && cert.Verify() ); return valid; } internal bool ValidateCertificate(X509Certificate2 certificateX509, out X509ChainStatus[] chainStatus, LogLevel logLevel = LogLevel.Warning) { var certificateChain = new X509Chain(); certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.Online; certificateChain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot; certificateChain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag; certificateChain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 0, 30); certificateChain.Build(certificateX509); chainStatus = certificateChain.ChainStatus; _logger?.Log(logLevel, "Certificate status: {ObjStatusInformation}", certificateChain.ChainStatus.Aggregate("", (r, s) => r + "\n\t - " + s.Status + ": " + s.StatusInformation)); return certificateChain.ChainStatus.Length == 0; } }