internal static GeneralName Read(DerSequenceReader reader) { var tag = reader.PeekTag(); // Per RFC 2634 section 5.4.1 (https://tools.ietf.org/html/rfc2634#section-5.4.1) // only the directory name choice (#4) is allowed. if (tag == DerSequenceReader.ContextSpecificConstructedTag4) { var value = reader.ReadValue((DerSequenceReader.DerTag)DerSequenceReader.ContextSpecificConstructedTag4); if (reader.HasData) { throw new SignatureException(Strings.InvalidAsn1); } var directoryName = new X500DistinguishedName(value); return(new GeneralName(directoryName)); } while (reader.HasData) { reader.ValidateAndSkipDerValue(); } throw new SignatureException(Strings.UnsupportedAsn1); }
/// <summary> /// Determines if a certificate is self-issued. /// </summary> /// <remarks>Warning: this method does not evaluate certificate trust, revocation status, or validity! /// This method attempts to build a chain for the provided certificate, and although revocation status /// checking is explicitly skipped, the underlying chain building engine may go online to fetch /// additional information (e.g.: the issuer's certificate). This method is not a guaranteed offline /// check.</remarks> /// <param name="certificate">The certificate to check.</param> /// <returns><c>true</c> if the certificate is self-issued; otherwise, <c>false</c>.</returns> /// <exception cref="ArgumentNullException">Thrown if <paramref name="certificate" /> is <c>null</c>.</exception> public static bool IsSelfIssued(X509Certificate2 certificate) { if (certificate == null) { throw new ArgumentNullException(nameof(certificate)); } using (var chainHolder = new X509ChainHolder()) { var chain = chainHolder.Chain; chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority | X509VerificationFlags.IgnoreRootRevocationUnknown | X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown | X509VerificationFlags.IgnoreEndRevocationUnknown; chain.Build(certificate); if (chain.ChainElements.Count != 1) { return(false); } if (chain.ChainStatus.Any( chainStatus => chainStatus.Status.HasFlag(X509ChainStatusFlags.Cyclic) || chainStatus.Status.HasFlag(X509ChainStatusFlags.PartialChain) || chainStatus.Status.HasFlag(X509ChainStatusFlags.NotSignatureValid))) { return(false); } if (!certificate.IssuerName.RawData.SequenceEqual(certificate.SubjectName.RawData)) { return(false); } var akiExtension = certificate.Extensions[Oids.AuthorityKeyIdentifier]; var skiExtension = certificate.Extensions[Oids.SubjectKeyIdentifier] as X509SubjectKeyIdentifierExtension; if (akiExtension != null && skiExtension != null) { var reader = new DerSequenceReader(akiExtension.RawData); var keyIdentifierTag = (DerSequenceReader.DerTag)DerSequenceReader.ContextSpecificTagFlag; if (reader.HasTag(keyIdentifierTag)) { var keyIdentifier = reader.ReadValue(keyIdentifierTag); var akiKeyIdentifier = BitConverter.ToString(keyIdentifier).Replace("-", ""); return(string.Equals(skiExtension.SubjectKeyIdentifier, akiKeyIdentifier, StringComparison.OrdinalIgnoreCase)); } } return(true); } }