/// <summary> /// Find all certificates that are not self-signed and has key usage "digital signature". /// Then sort all certificates, so that issuers are after the certificates they sign. /// Certificates in the list that were not part of the trust chain for the digital signatures are not retained. /// </summary> /// <returns>sorted certificates needed to verify the digital signatures from the input list</returns> static List <X509Certificate2> SortCertificatesIssuerLast(IEnumerable <X509Certificate2> inputCertificates) { var result = new List <X509Certificate2>(); var certBySubject = new Dictionary <string, X509Certificate2>(); foreach (var certificate in inputCertificates) { certBySubject[certificate.Subject] = certificate; var keyUsage = X509CertificatePropertyExtrator.GetKeyUsage(certificate); if (keyUsage != null && keyUsage.KeyUsages.ToString().Contains("DigitalSignature") && !keyUsage.KeyUsages.ToString().Contains("CrlSign")) { result.Add(certificate); } } for (var i = 0; i < result.Count; i++) { var certificate = result[i]; if (!certBySubject.ContainsKey(certificate.Issuer)) { continue; } var issuer = certBySubject[result[i].Issuer]; if (!result.Contains(issuer)) { result.Add(issuer); } } return(result); }
private static bool VerifyChain(Ca ca, int pathLength) { var basicConstraints = X509CertificatePropertyExtrator.GetBasicConstraints(ca.Certificate); //check that CA certificate is in fact a CA if (!basicConstraints.CertificateAuthority) { return(false); } //check that CA certificate must sign other certificates X509KeyUsageFlags flags = X509CertificatePropertyExtrator.GetKeyUsage(ca.Certificate).KeyUsages; if ((flags & (X509KeyUsageFlags.KeyCertSign)) != X509KeyUsageFlags.KeyCertSign) { return(false); } // Check path length if (basicConstraints.HasPathLengthConstraint && basicConstraints.PathLengthConstraint < pathLength) { return(false); } if (IsSelfSigned(ca) && !ca.IsRoot) { return(false); } if (ca.IsRoot) { return(true); } if (ca.IssuingCa == null) { return(false); } Ca signingCa = ca.IssuingCa; if (X509CertificatePropertyExtrator.GetBasicConstraints(signingCa.Certificate).PathLengthConstraint >= 0) { if (Verify(ca.Certificate, GetPublicKey(signingCa.Certificate))) { return(VerifyChain(ca.IssuingCa, ++pathLength)); } } return(false); }