Exemple #1
0
        public void RemoveCounterSignature(SignerInfo counterSignerInfo)
        {
            // We only support one level of counter signing.
            if (m_parentSignerInfo != null)
            {
                throw new CryptographicException(CAPI.E_NOTIMPL);
            }
            if (counterSignerInfo == null)
            {
                throw new ArgumentNullException("counterSignerInfo");
            }

            foreach (CryptographicAttributeObject attribute in UnsignedAttributes)
            {
                if (String.Compare(attribute.Oid.Value, CAPI.szOID_RSA_counterSign, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    for (int index = 0; index < attribute.Values.Count; index++)
                    {
                        AsnEncodedData encodedCounterSignature = (AsnEncodedData)attribute.Values[index];
                        SignerInfo     counterSignerInfo2      = new SignerInfo(m_signedCms, m_parentSignerInfo, encodedCounterSignature.RawData);

                        if ((counterSignerInfo.SignerIdentifier.Type == SubjectIdentifierType.IssuerAndSerialNumber) &&
                            (counterSignerInfo2.SignerIdentifier.Type == SubjectIdentifierType.IssuerAndSerialNumber))
                        {
                            X509IssuerSerial issuerSerial1 = (X509IssuerSerial)counterSignerInfo.SignerIdentifier.Value;
                            X509IssuerSerial issuerSerial2 = (X509IssuerSerial)counterSignerInfo2.SignerIdentifier.Value;

                            if ((String.Compare(issuerSerial1.IssuerName, issuerSerial2.IssuerName, StringComparison.OrdinalIgnoreCase) == 0) &&
                                (String.Compare(issuerSerial1.SerialNumber, issuerSerial2.SerialNumber, StringComparison.OrdinalIgnoreCase) == 0))
                            {
                                RemoveCounterSignature(PkcsUtils.GetSignerIndex(m_signedCms.GetCryptMsgHandle(), this, 0), index);
                                return;
                            }
                        }
                        else if ((counterSignerInfo.SignerIdentifier.Type == SubjectIdentifierType.SubjectKeyIdentifier) &&
                                 (counterSignerInfo2.SignerIdentifier.Type == SubjectIdentifierType.SubjectKeyIdentifier))
                        {
                            string keyIdentifier1 = counterSignerInfo.SignerIdentifier.Value as string;
                            string keyIdentifier2 = counterSignerInfo2.SignerIdentifier.Value as string;

                            if (String.Compare(keyIdentifier1, keyIdentifier2, StringComparison.OrdinalIgnoreCase) == 0)
                            {
                                RemoveCounterSignature(PkcsUtils.GetSignerIndex(m_signedCms.GetCryptMsgHandle(), this, 0), index);
                                return;
                            }
                        }
                    }
                }
            }

            throw new CryptographicException(CAPI.CRYPT_E_SIGNER_NOT_FOUND);
        }
Exemple #2
0
        // methods

        private X509IssuerSerial GetIssuerSerial(string issuer, byte[] serial)
        {
            X509IssuerSerial xis = new X509IssuerSerial();

            xis.IssuerName = issuer;
            StringBuilder sb = new StringBuilder();

            foreach (byte b in serial)
            {
                sb.Append(b.ToString("X2"));
            }
            xis.SerialNumber = sb.ToString();
            return(xis);
        }
Exemple #3
0
        public void RemoveCounterSignature(SignerInfo counterSignerInfo)
        {
            if (this.m_parentSignerInfo != null)
            {
                throw new CryptographicException(-2147483647);
            }
            if (counterSignerInfo == null)
            {
                throw new ArgumentNullException("counterSignerInfo");
            }
            CryptographicAttributeObjectEnumerator enumerator = this.UnsignedAttributes.GetEnumerator();

            while (enumerator.MoveNext())
            {
                CryptographicAttributeObject current = enumerator.Current;
                if (string.Compare(current.Oid.Value, "1.2.840.113549.1.9.6", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    for (int i = 0; i < current.Values.Count; i++)
                    {
                        AsnEncodedData data = current.Values[i];
                        SignerInfo     info = new SignerInfo(this.m_signedCms, this.m_parentSignerInfo, data.RawData);
                        if ((counterSignerInfo.SignerIdentifier.Type == SubjectIdentifierType.IssuerAndSerialNumber) && (info.SignerIdentifier.Type == SubjectIdentifierType.IssuerAndSerialNumber))
                        {
                            X509IssuerSerial serial  = (X509IssuerSerial)counterSignerInfo.SignerIdentifier.Value;
                            X509IssuerSerial serial2 = (X509IssuerSerial)info.SignerIdentifier.Value;
                            if ((string.Compare(serial.IssuerName, serial2.IssuerName, StringComparison.OrdinalIgnoreCase) != 0) || (string.Compare(serial.SerialNumber, serial2.SerialNumber, StringComparison.OrdinalIgnoreCase) != 0))
                            {
                                continue;
                            }
                            this.RemoveCounterSignature(PkcsUtils.GetSignerIndex(this.m_signedCms.GetCryptMsgHandle(), this, 0), i);
                            return;
                        }
                        if ((counterSignerInfo.SignerIdentifier.Type == SubjectIdentifierType.SubjectKeyIdentifier) && (info.SignerIdentifier.Type == SubjectIdentifierType.SubjectKeyIdentifier))
                        {
                            string strA = counterSignerInfo.SignerIdentifier.Value as string;
                            string strB = info.SignerIdentifier.Value as string;
                            if (string.Compare(strA, strB, StringComparison.OrdinalIgnoreCase) == 0)
                            {
                                this.RemoveCounterSignature(PkcsUtils.GetSignerIndex(this.m_signedCms.GetCryptMsgHandle(), this, 0), i);
                                return;
                            }
                        }
                    }
                }
            }
            throw new CryptographicException(-2146889714);
        }
Exemple #4
0
        public void Decode(byte[] encodedMessage)
        {
            if (encodedMessage == null)
            {
                throw new ArgumentNullException("encodedMessage");
            }

            PKCS7.ContentInfo ci = new PKCS7.ContentInfo(encodedMessage);
            if (ci.ContentType != PKCS7.Oid.envelopedData)
            {
                throw new Exception("");
            }

            PKCS7.EnvelopedData ed = new PKCS7.EnvelopedData(ci.Content);

            Oid oid = new Oid(ed.ContentInfo.ContentType);

            _content = new ContentInfo(oid, new byte [0]);              //ed.ContentInfo.Content.Value);

            foreach (PKCS7.RecipientInfo ri in ed.RecipientInfos)
            {
                Oid o = new Oid(ri.Oid);
                AlgorithmIdentifier ai = new AlgorithmIdentifier(o);
                SubjectIdentifier   si = null;
                if (ri.SubjectKeyIdentifier != null)
                {
                    si = new SubjectIdentifier(SubjectIdentifierType.SubjectKeyIdentifier, ri.SubjectKeyIdentifier);
                }
                else if ((ri.Issuer != null) && (ri.Serial != null))
                {
                    X509IssuerSerial xis = GetIssuerSerial(ri.Issuer, ri.Serial);
                    si = new SubjectIdentifier(SubjectIdentifierType.IssuerAndSerialNumber, (object)xis);
                }

                KeyTransRecipientInfo _keyTrans = new KeyTransRecipientInfo(ri.Key, ai, si, ri.Version);
                _recipients.Add(_keyTrans);
            }

            // TODO - Certificates
            // TODO - UnprotectedAttributes

            _version = ed.Version;
        }
Exemple #5
0
        internal SubjectIdentifierOrKey(CAPI.CERT_ID certId)
        {
            switch (certId.dwIdChoice)
            {
            case CAPI.CERT_ID_ISSUER_SERIAL_NUMBER:
                X509IssuerSerial issuerSerial = PkcsUtils.DecodeIssuerSerial(certId.Value.IssuerSerialNumber);
                Reset(SubjectIdentifierOrKeyType.IssuerAndSerialNumber, issuerSerial);
                break;

            case CAPI.CERT_ID_KEY_IDENTIFIER:
                byte[] ski = new byte[certId.Value.KeyId.cbData];
                Marshal.Copy(certId.Value.KeyId.pbData, ski, 0, ski.Length);
                Reset(SubjectIdentifierOrKeyType.SubjectKeyIdentifier, X509Utils.EncodeHexString(ski));
                break;

            default:
                throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Cms_Invalid_Subject_Identifier_Type"), certId.dwIdChoice.ToString(CultureInfo.InvariantCulture));
            }
        }
        internal SubjectIdentifier(System.Security.Cryptography.CAPI.CERT_ID certId)
        {
            switch (certId.dwIdChoice)
            {
            case 1:
            {
                X509IssuerSerial serial = PkcsUtils.DecodeIssuerSerial(certId.Value.IssuerSerialNumber);
                this.Reset(SubjectIdentifierType.IssuerAndSerialNumber, serial);
                return;
            }

            case 2:
            {
                byte[] destination = new byte[certId.Value.KeyId.cbData];
                Marshal.Copy(certId.Value.KeyId.pbData, destination, 0, destination.Length);
                this.Reset(SubjectIdentifierType.SubjectKeyIdentifier, System.Security.Cryptography.X509Certificates.X509Utils.EncodeHexString(destination));
                return;
            }
            }
            throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Cms_Invalid_Subject_Identifier_Type"), certId.dwIdChoice.ToString(CultureInfo.InvariantCulture));
        }
        internal static X509Certificate2 FindCertificate(SubjectIdentifier identifier, X509Certificate2Collection certificates)
        {
            X509Certificate2 certificate = null;

            if ((certificates != null) && (certificates.Count > 0))
            {
                X509Certificate2Collection certificates2;
                switch (identifier.Type)
                {
                case SubjectIdentifierType.IssuerAndSerialNumber:
                {
                    X509IssuerSerial serial = (X509IssuerSerial)identifier.Value;
                    certificates2 = certificates.Find(X509FindType.FindByIssuerDistinguishedName, serial.IssuerName, false);
                    if (certificates2.Count > 0)
                    {
                        X509IssuerSerial serial2 = (X509IssuerSerial)identifier.Value;
                        certificates2 = certificates2.Find(X509FindType.FindBySerialNumber, serial2.SerialNumber, false);
                        if (certificates2.Count > 0)
                        {
                            certificate = certificates2[0];
                        }
                    }
                    return(certificate);
                }

                case SubjectIdentifierType.SubjectKeyIdentifier:
                    certificates2 = certificates.Find(X509FindType.FindBySubjectKeyIdentifier, identifier.Value, false);
                    if (certificates2.Count > 0)
                    {
                        certificate = certificates2[0];
                    }
                    return(certificate);
                }
            }
            return(certificate);
        }
        internal static unsafe X509IssuerSerial DecodeIssuerSerial(System.Security.Cryptography.CAPI.CERT_ISSUER_SERIAL_NUMBER pIssuerAndSerial)
        {
            System.Security.Cryptography.SafeLocalAllocHandle invalidHandle = System.Security.Cryptography.SafeLocalAllocHandle.InvalidHandle;
            uint csz = System.Security.Cryptography.CAPI.CAPISafe.CertNameToStrW(0x10001, new IntPtr((void *)&pIssuerAndSerial.Issuer), 0x2000003, invalidHandle, 0);

            if (csz <= 1)
            {
                throw new CryptographicException(Marshal.GetLastWin32Error());
            }
            invalidHandle = System.Security.Cryptography.CAPI.LocalAlloc(0, new IntPtr((long)(2 * csz)));
            if (System.Security.Cryptography.CAPI.CAPISafe.CertNameToStrW(0x10001, new IntPtr((void *)&pIssuerAndSerial.Issuer), 0x2000003, invalidHandle, csz) <= 1)
            {
                throw new CryptographicException(Marshal.GetLastWin32Error());
            }
            X509IssuerSerial serial = new X509IssuerSerial {
                IssuerName = Marshal.PtrToStringUni(invalidHandle.DangerousGetHandle())
            };

            byte[] destination = new byte[pIssuerAndSerial.SerialNumber.cbData];
            Marshal.Copy(pIssuerAndSerial.SerialNumber.pbData, destination, 0, destination.Length);
            serial.SerialNumber = System.Security.Cryptography.X509Certificates.X509Utils.EncodeHexStringFromInt(destination);
            invalidHandle.Dispose();
            return(serial);
        }
Exemple #9
0
        public void Decode(byte[] encodedMessage)
        {
            PKCS7.ContentInfo ci = new PKCS7.ContentInfo(encodedMessage);
            if (ci.ContentType != PKCS7.Oid.signedData)
            {
                throw new Exception("");
            }

            PKCS7.SignedData      sd   = new PKCS7.SignedData(ci.Content);
            SubjectIdentifierType type = SubjectIdentifierType.Unknown;
            object o = null;

            X509Certificate2 x509 = null;

            if (sd.SignerInfo.Certificate != null)
            {
                x509 = new X509Certificate2(sd.SignerInfo.Certificate.RawData);
            }
            else if ((sd.SignerInfo.IssuerName != null) && (sd.SignerInfo.SerialNumber != null))
            {
                byte[] serial = sd.SignerInfo.SerialNumber;
                Array.Reverse(serial);                  // ???
                type = SubjectIdentifierType.IssuerAndSerialNumber;
                X509IssuerSerial xis = new X509IssuerSerial();
                xis.IssuerName   = sd.SignerInfo.IssuerName;
                xis.SerialNumber = ToString(serial, true);
                o = xis;
                // TODO: move to a FindCertificate (issuer, serial, collection)
                foreach (Mono.Security.X509.X509Certificate x in sd.Certificates)
                {
                    if (x.IssuerName == sd.SignerInfo.IssuerName)
                    {
                        if (ToString(x.SerialNumber, true) == xis.SerialNumber)
                        {
                            x509 = new X509Certificate2(x.RawData);
                            break;
                        }
                    }
                }
            }
            else if (sd.SignerInfo.SubjectKeyIdentifier != null)
            {
                string ski = ToString(sd.SignerInfo.SubjectKeyIdentifier, false);
                type = SubjectIdentifierType.SubjectKeyIdentifier;
                o    = (object)ski;
                // TODO: move to a FindCertificate (ski, collection)
                foreach (Mono.Security.X509.X509Certificate x in sd.Certificates)
                {
                    if (ToString(GetKeyIdentifier(x), false) == ski)
                    {
                        x509 = new X509Certificate2(x.RawData);
                        break;
                    }
                }
            }

            SignerInfo si = new SignerInfo(sd.SignerInfo.HashName, x509, type, o, sd.SignerInfo.Version);

            // si.AuthenticatedAttributes
            // si.UnauthenticatedAttributes
            _info.Add(si);

            ASN1 content = sd.ContentInfo.Content;
            Oid  oid     = new Oid(sd.ContentInfo.ContentType);

            if (!_detached || _content == null)
            {
                if (content[0] == null)
                {
                    throw new ArgumentException("ContentInfo has no content. Detached signature ?");
                }

                _content = new ContentInfo(oid, content[0].Value);
            }

            foreach (Mono.Security.X509.X509Certificate x in sd.Certificates)
            {
                _certs.Add(new X509Certificate2(x.RawData));
            }

            _version = sd.Version;
        }
        internal unsafe SubjectIdentifier(System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB issuer, System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB serialNumber)
        {
            System.Security.Cryptography.CAPI.CERT_ISSUER_SERIAL_NUMBER cert_issuer_serial_number;
            bool  flag   = true;
            byte *pbData = (byte *)serialNumber.pbData;

            for (uint i = 0; i < serialNumber.cbData; i++)
            {
                pbData++;
                if (pbData[0] != 0)
                {
                    flag = false;
                    break;
                }
            }
            if (flag)
            {
                byte[] destination = new byte[issuer.cbData];
                Marshal.Copy(issuer.pbData, destination, 0, destination.Length);
                X500DistinguishedName name = new X500DistinguishedName(destination);
                if (string.Compare("CN=Dummy Signer", name.Name, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    this.Reset(SubjectIdentifierType.NoSignature, null);
                    return;
                }
            }
            if (flag)
            {
                this.m_type  = SubjectIdentifierType.SubjectKeyIdentifier;
                this.m_value = string.Empty;
                uint cbDecodedValue = 0;
                System.Security.Cryptography.SafeLocalAllocHandle invalidHandle = System.Security.Cryptography.SafeLocalAllocHandle.InvalidHandle;
                if (!System.Security.Cryptography.CAPI.DecodeObject(new IntPtr(7L), issuer.pbData, issuer.cbData, out invalidHandle, out cbDecodedValue))
                {
                    throw new CryptographicException(Marshal.GetLastWin32Error());
                }
                using (invalidHandle)
                {
                    System.Security.Cryptography.CAPI.CERT_NAME_INFO cert_name_info = (System.Security.Cryptography.CAPI.CERT_NAME_INFO)Marshal.PtrToStructure(invalidHandle.DangerousGetHandle(), typeof(System.Security.Cryptography.CAPI.CERT_NAME_INFO));
                    for (uint j = 0; j < cert_name_info.cRDN; j++)
                    {
                        System.Security.Cryptography.CAPI.CERT_RDN cert_rdn = (System.Security.Cryptography.CAPI.CERT_RDN)Marshal.PtrToStructure(new IntPtr(((long)cert_name_info.rgRDN) + (j * Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CERT_RDN)))), typeof(System.Security.Cryptography.CAPI.CERT_RDN));
                        for (uint k = 0; k < cert_rdn.cRDNAttr; k++)
                        {
                            System.Security.Cryptography.CAPI.CERT_RDN_ATTR cert_rdn_attr = (System.Security.Cryptography.CAPI.CERT_RDN_ATTR)Marshal.PtrToStructure(new IntPtr(((long)cert_rdn.rgRDNAttr) + (k * Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CERT_RDN_ATTR)))), typeof(System.Security.Cryptography.CAPI.CERT_RDN_ATTR));
                            if ((string.Compare("1.3.6.1.4.1.311.10.7.1", cert_rdn_attr.pszObjId, StringComparison.OrdinalIgnoreCase) == 0) && (cert_rdn_attr.dwValueType == 2))
                            {
                                byte[] buffer2 = new byte[cert_rdn_attr.Value.cbData];
                                Marshal.Copy(cert_rdn_attr.Value.pbData, buffer2, 0, buffer2.Length);
                                this.Reset(SubjectIdentifierType.SubjectKeyIdentifier, System.Security.Cryptography.X509Certificates.X509Utils.EncodeHexString(buffer2));
                                return;
                            }
                        }
                    }
                }
                throw new CryptographicException(-2146889715);
            }
            cert_issuer_serial_number.Issuer       = issuer;
            cert_issuer_serial_number.SerialNumber = serialNumber;
            X509IssuerSerial serial = PkcsUtils.DecodeIssuerSerial(cert_issuer_serial_number);

            this.Reset(SubjectIdentifierType.IssuerAndSerialNumber, serial);
        }
Exemple #11
0
        internal unsafe SubjectIdentifier(CAPI.CRYPTOAPI_BLOB issuer, CAPI.CRYPTOAPI_BLOB serialNumber)
        {
            // If serial number is 0, then it is the special SKI encoding or NoSignature
            bool  isSKIorHashOnly = true;
            byte *pb = (byte *)serialNumber.pbData;

            for (uint i = 0; i < serialNumber.cbData; i++)
            {
                if (*pb++ != (byte)0)
                {
                    isSKIorHashOnly = false;
                    break;
                }
            }

            if (isSKIorHashOnly)
            {
                byte[] issuerBytes = new byte[issuer.cbData];
                Marshal.Copy(issuer.pbData, issuerBytes, 0, issuerBytes.Length);
                X500DistinguishedName dummyName = new X500DistinguishedName(issuerBytes);
                if (String.Compare(CAPI.DummySignerCommonName, dummyName.Name, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    Reset(SubjectIdentifierType.NoSignature, null);
                    return;
                }
            }

            if (isSKIorHashOnly)
            {
                // Decode disguised SKI in issuer field (See WinCrypt.h for more info).  Note that some certificates may contain
                // an all-zero serial number but not be encoded with an szOID_KEYID_RDN.  In order to allow use of signatures created
                // using these certificates, we will first try to find the szOID_KEYID_RDN, but if it does not exist, fall back to just
                // decoding the incoming issuer and serial number.
                m_type  = SubjectIdentifierType.SubjectKeyIdentifier;
                m_value = String.Empty;

                uint cbCertNameInfo = 0;
                SafeLocalAllocHandle pbCertNameInfo = SafeLocalAllocHandle.InvalidHandle;

                if (CAPI.DecodeObject(new IntPtr(CAPI.X509_NAME),
                                      issuer.pbData,
                                      issuer.cbData,
                                      out pbCertNameInfo,
                                      out cbCertNameInfo))
                {
                    using (pbCertNameInfo) {
                        checked {
                            CAPI.CERT_NAME_INFO certNameInfo = (CAPI.CERT_NAME_INFO)Marshal.PtrToStructure(pbCertNameInfo.DangerousGetHandle(), typeof(CAPI.CERT_NAME_INFO));
                            for (uint i = 0; i < certNameInfo.cRDN; i++)
                            {
                                CAPI.CERT_RDN certRdn = (CAPI.CERT_RDN)Marshal.PtrToStructure(new IntPtr((long)certNameInfo.rgRDN + (long)(i * Marshal.SizeOf(typeof(CAPI.CERT_RDN)))), typeof(CAPI.CERT_RDN));

                                for (uint j = 0; j < certRdn.cRDNAttr; j++)
                                {
                                    CAPI.CERT_RDN_ATTR certRdnAttr = (CAPI.CERT_RDN_ATTR)Marshal.PtrToStructure(new IntPtr((long)certRdn.rgRDNAttr + (long)(j * Marshal.SizeOf(typeof(CAPI.CERT_RDN_ATTR)))), typeof(CAPI.CERT_RDN_ATTR));

                                    if (String.Compare(CAPI.szOID_KEYID_RDN, certRdnAttr.pszObjId, StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        if (certRdnAttr.dwValueType == CAPI.CERT_RDN_OCTET_STRING)
                                        {
                                            byte[] ski = new byte[certRdnAttr.Value.cbData];
                                            Marshal.Copy(certRdnAttr.Value.pbData, ski, 0, ski.Length);
                                            Reset(SubjectIdentifierType.SubjectKeyIdentifier, X509Utils.EncodeHexString(ski));
                                            return;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            CAPI.CERT_ISSUER_SERIAL_NUMBER IssuerAndSerial;
            IssuerAndSerial.Issuer       = issuer;
            IssuerAndSerial.SerialNumber = serialNumber;
            X509IssuerSerial issuerSerial = PkcsUtils.DecodeIssuerSerial(IssuerAndSerial);

            Reset(SubjectIdentifierType.IssuerAndSerialNumber, issuerSerial);
        }
Exemple #12
0
        public static bool TryDecode(ReadOnlyMemory <byte> source, out Rfc3161TimestampToken token, out int bytesConsumed)
        {
            bytesConsumed = 0;
            token         = null;

            try
            {
                ContentInfoAsn contentInfo =
                    AsnSerializer.Deserialize <ContentInfoAsn>(source, AsnEncodingRules.BER, out int bytesActuallyRead);

                // https://tools.ietf.org/html/rfc3161#section-2.4.2
                //
                // A TimeStampToken is as follows.  It is defined as a ContentInfo
                // ([CMS]) and SHALL encapsulate a signed data content type.
                //
                // TimeStampToken::= ContentInfo
                //   --contentType is id-signedData([CMS])
                //   --content is SignedData ([CMS])
                if (contentInfo.ContentType != Oids.Pkcs7Signed)
                {
                    return(false);
                }

                SignedCms cms = new SignedCms();
                cms.Decode(source);

                // The fields of type EncapsulatedContentInfo of the SignedData
                // construct have the following meanings:
                //
                // eContentType is an object identifier that uniquely specifies the
                // content type.  For a time-stamp token it is defined as:
                //
                // id-ct-TSTInfo  OBJECT IDENTIFIER ::= { iso(1) member-body(2)
                // us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1) 4}
                //
                // eContent is the content itself, carried as an octet string.
                // The eContent SHALL be the DER-encoded value of TSTInfo.
                if (cms.ContentInfo.ContentType.Value != Oids.TstInfo)
                {
                    return(false);
                }

                // RFC3161:
                // The time-stamp token MUST NOT contain any signatures other than the
                // signature of the TSA.  The certificate identifier (ESSCertID) of the
                // TSA certificate MUST be included as a signerInfo attribute inside a
                // SigningCertificate attribute.

                // RFC5816 says that ESSCertIDv2 should be allowed instead.

                SignerInfoCollection signerInfos = cms.SignerInfos;

                if (signerInfos.Count != 1)
                {
                    return(false);
                }

                SignerInfo  signer = signerInfos[0];
                EssCertId   certId;
                EssCertIdV2 certId2;

                if (!TryGetCertIds(signer, out certId, out certId2))
                {
                    return(false);
                }

                X509Certificate2 signerCert = signer.Certificate;

                if (signerCert == null &&
                    signer.SignerIdentifier.Type == SubjectIdentifierType.IssuerAndSerialNumber)
                {
                    // If the cert wasn't provided, but the identifier was IssuerAndSerialNumber,
                    // and the ESSCertId(V2) has specified an issuerSerial value, ensure it's a match.
                    X509IssuerSerial issuerSerial = (X509IssuerSerial)signer.SignerIdentifier.Value;

                    if (certId?.IssuerSerial != null)
                    {
                        if (!IssuerAndSerialMatch(
                                certId.IssuerSerial.Value,
                                issuerSerial.IssuerName,
                                issuerSerial.SerialNumber))
                        {
                            return(false);
                        }
                    }

                    if (certId2?.IssuerSerial != null)
                    {
                        if (!IssuerAndSerialMatch(
                                certId2.IssuerSerial.Value,
                                issuerSerial.IssuerName,
                                issuerSerial.SerialNumber))
                        {
                            return(false);
                        }
                    }
                }

                Rfc3161TimestampTokenInfo tokenInfo;

                if (Rfc3161TimestampTokenInfo.TryDecode(cms.ContentInfo.Content, out tokenInfo, out _))
                {
                    if (signerCert != null &&
                        !CheckCertificate(signerCert, signer, certId, certId2, tokenInfo))
                    {
                        return(false);
                    }

                    token = new Rfc3161TimestampToken
                    {
                        _parsedDocument = cms,
                        _signerInfo     = signer,
                        _essCertId      = certId,
                        _essCertIdV2    = certId2,
                        TokenInfo       = tokenInfo,
                    };

                    bytesConsumed = bytesActuallyRead;
                    return(true);
                }
            }
            catch (CryptographicException)
            {
            }

            return(false);
        }
        internal int FindIndexForSigner(SignerInfo signer)
        {
            Debug.Assert(signer != null);
            SubjectIdentifier id           = signer.SignerIdentifier;
            X509IssuerSerial  issuerSerial = default;

            if (id.Type == SubjectIdentifierType.IssuerAndSerialNumber)
            {
                issuerSerial = (X509IssuerSerial)id.Value;
            }

            for (int i = 0; i < _signerInfos.Length; i++)
            {
                SignerInfo        current   = _signerInfos[i];
                SubjectIdentifier currentId = current.SignerIdentifier;

                if (currentId.Type != id.Type)
                {
                    continue;
                }

                bool equal = false;

                switch (id.Type)
                {
                case SubjectIdentifierType.IssuerAndSerialNumber:
                {
                    X509IssuerSerial currentIssuerSerial = (X509IssuerSerial)currentId.Value;

                    if (currentIssuerSerial.IssuerName == issuerSerial.IssuerName &&
                        currentIssuerSerial.SerialNumber == issuerSerial.SerialNumber)
                    {
                        equal = true;
                    }

                    break;
                }

                case SubjectIdentifierType.SubjectKeyIdentifier:
                    if ((string)id.Value == (string)currentId.Value)
                    {
                        equal = true;
                    }

                    break;

                case SubjectIdentifierType.NoSignature:
                    equal = true;
                    break;

                default:
                    Debug.Fail($"No match logic for SubjectIdentifierType {id.Type}");
                    throw new CryptographicException();
                }

                if (equal)
                {
                    return(i);
                }
            }

            return(-1);
        }