コード例 #1
0
        public static void TagMustBeCorrect_Custom(AsnEncodingRules ruleSet)
        {
            byte[]    inputData = "87028837".HexToByteArray();
            AsnReader reader    = new AsnReader(inputData, ruleSet);

            AssertExtensions.Throws <ArgumentException>(
                "expectedTag",
                () => reader.ReadIntegerBytes(Asn1Tag.Null));

            Assert.True(reader.HasData, "HasData after bad universal tag");

            Assert.Throws <AsnContentException>(() => reader.ReadObjectIdentifier());

            Assert.True(reader.HasData, "HasData after default tag");

            Assert.Throws <AsnContentException>(
                () => reader.ReadObjectIdentifier(new Asn1Tag(TagClass.Application, 0)));

            Assert.True(reader.HasData, "HasData after wrong custom class");

            Assert.Throws <AsnContentException>(
                () => reader.ReadObjectIdentifier(new Asn1Tag(TagClass.ContextSpecific, 1)));

            Assert.True(reader.HasData, "HasData after wrong custom tag value");

            Assert.Equal(
                "2.999",
                reader.ReadObjectIdentifier(new Asn1Tag(TagClass.ContextSpecific, 7)));

            Assert.False(reader.HasData, "HasData after reading value");
        }
コード例 #2
0
        private static void ReadEcPublicKey(AsnEncodingRules ruleSet, byte[] inputData)
        {
            AsnReader mainReader = new AsnReader(inputData, ruleSet);

            AsnReader spkiReader = mainReader.ReadSequence();

            Assert.False(mainReader.HasData, "mainReader.HasData after reading SPKI");

            AsnReader algorithmReader = spkiReader.ReadSequence();

            Assert.True(spkiReader.HasData, "spkiReader.HasData after reading algorithm");

            ReadOnlyMemory <byte> publicKeyValue;
            int unusedBitCount;

            if (!spkiReader.TryReadPrimitiveBitStringValue(out unusedBitCount, out publicKeyValue))
            {
                // The correct answer is 65 bytes.
                for (int i = 10; ; i *= 2)
                {
                    byte[] buf = new byte[i];

                    if (spkiReader.TryCopyBitStringBytes(buf, out unusedBitCount, out int bytesWritten))
                    {
                        publicKeyValue = new ReadOnlyMemory <byte>(buf, 0, bytesWritten);
                        break;
                    }
                }
            }

            Assert.False(spkiReader.HasData, "spkiReader.HasData after reading subjectPublicKey");
            Assert.True(algorithmReader.HasData, "algorithmReader.HasData before reading");

            Oid algorithmOid = algorithmReader.ReadObjectIdentifier();

            Assert.True(algorithmReader.HasData, "algorithmReader.HasData after reading first OID");

            Assert.Equal("1.2.840.10045.2.1", algorithmOid.Value);

            Oid curveOid = algorithmReader.ReadObjectIdentifier();

            Assert.False(algorithmReader.HasData, "algorithmReader.HasData after reading second OID");

            Assert.Equal("1.2.840.10045.3.1.7", curveOid.Value);

            const string PublicKeyValue =
                "04" +
                "2363DD131DA65E899A2E63E9E05E50C830D4994662FFE883DB2B9A767DCCABA2" +
                "F07081B5711BE1DEE90DFC8DE17970C2D937A16CD34581F52B8D59C9E9532D13";

            Assert.Equal(PublicKeyValue, publicKeyValue.ByteArrayToHex());
            Assert.Equal(0, unusedBitCount);
        }
コード例 #3
0
        public virtual void DecodeX509EnhancedKeyUsageExtension(byte[] encoded, out OidCollection usages)
        {
            // https://tools.ietf.org/html/rfc5924#section-4.1
            //
            // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
            //
            // KeyPurposeId ::= OBJECT IDENTIFIER

            try
            {
                AsnReader reader         = new AsnReader(encoded, AsnEncodingRules.BER);
                AsnReader sequenceReader = reader.ReadSequence();
                reader.ThrowIfNotEmpty();
                usages = new OidCollection();

                while (sequenceReader.HasData)
                {
                    usages.Add(new Oid(sequenceReader.ReadObjectIdentifier(), null));
                }
            }
            catch (AsnContentException e)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
            }
        }
コード例 #4
0
ファイル: X501AttributeAsn.xml.cs プロジェクト: yunly/corefx
        internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out X501AttributeAsn decoded)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            decoded = default;
            AsnReader sequenceReader = reader.ReadSequence(expectedTag);
            AsnReader collectionReader;

            decoded.AttrId = sequenceReader.ReadObjectIdentifier();

            // Decode SEQUENCE OF for AttrValues
            {
                collectionReader = sequenceReader.ReadSetOf();
                var tmpList = new List <ReadOnlyMemory <byte> >();
                ReadOnlyMemory <byte> tmpItem;

                while (collectionReader.HasData)
                {
                    tmpItem = collectionReader.GetEncodedValue();
                    tmpList.Add(tmpItem);
                }

                decoded.AttrValues = tmpList.ToArray();
            }


            sequenceReader.ThrowIfNotEmpty();
        }
コード例 #5
0
        public static void ReadVeryLongOidArc(AsnEncodingRules ruleSet)
        {
            byte[] inputData = new byte[255];
            // 06 81 93 (OBJECT IDENTIFIER, 147 bytes).
            inputData[0] = 0x06;
            inputData[1] = 0x81;
            inputData[2] = 0x93;

            // With 147 bytes we get 147*7 = 1029 value bits.
            // The smallest legal number to encode would have a top byte of 0x81,
            // leaving 1022 bits remaining.  If they're all zero then we have 2^1022.
            //
            // Since it's our first sub-identifier it's really encoding "2.(2^1022 - 80)".
            inputData[3] = 0x81;
            // Leave the last byte as 0.
            new Span <byte>(inputData, 4, 145).Fill(0x80);

            const string ExpectedOid =
                "2." +
                "449423283715578976932326297697256183404494244735576643183575" +
                "202894331689513752407831771193306018840052800284699678483394" +
                "146974422036041556232118576598685310944419733562163713190755" +
                "549003115235298632707380212514422095376705856157203684782776" +
                "352068092908376276711465745599868114846199290762088390824060" +
                "56034224";

            AsnReader reader = new AsnReader(inputData, ruleSet);

            string oidString = reader.ReadObjectIdentifier();

            Assert.Equal(ExpectedOid, oidString);
        }
コード例 #6
0
        public static void ReadVeryLongOid(AsnEncodingRules ruleSet)
        {
            byte[] inputData = new byte[100000];
            // 06 83 02 00 00 (OBJECT IDENTIFIER, 65536 bytes).
            inputData[0] = 0x06;
            inputData[1] = 0x83;
            inputData[2] = 0x01;
            inputData[3] = 0x00;
            inputData[4] = 0x00;
            // and the rest are all zero.

            // The first byte produces "0.0". Each of the remaining 65535 bytes produce
            // another ".0".
            const int     ExpectedLength = 65536 * 2 + 1;
            StringBuilder builder        = new StringBuilder(ExpectedLength);

            builder.Append('0');

            for (int i = 0; i <= ushort.MaxValue; i++)
            {
                builder.Append('.');
                builder.Append(0);
            }

            AsnReader reader    = new AsnReader(inputData, ruleSet);
            string    oidString = reader.ReadObjectIdentifier();

            Assert.Equal(ExpectedLength, oidString.Length);
            Assert.Equal(builder.ToString(), oidString);
        }
コード例 #7
0
        public static void VerifyMultiByteParsing(string inputHex, string expectedValue)
        {
            byte[]    inputData = inputHex.HexToByteArray();
            AsnReader reader    = new AsnReader(inputData, AsnEncodingRules.DER);

            string oidValue = reader.ReadObjectIdentifier();

            Assert.Equal(expectedValue, oidValue);
        }
コード例 #8
0
        public static void ReadObjectIdentifier_Throws(
            string description,
            PublicEncodingRules ruleSet,
            string inputHex)
        {
            byte[]    inputData = inputHex.HexToByteArray();
            AsnReader reader    = new AsnReader(inputData, (AsnEncodingRules)ruleSet);

            Assert.Throws <CryptographicException>(() => reader.ReadObjectIdentifier(true));
        }
コード例 #9
0
        public static void ReadObjectIdentifier_Throws(
            string description,
            AsnEncodingRules ruleSet,
            string inputHex)
        {
            _ = description;
            byte[]    inputData = inputHex.HexToByteArray();
            AsnReader reader    = new AsnReader(inputData, ruleSet);

            Assert.Throws <AsnContentException>(() => reader.ReadObjectIdentifier());
        }
コード例 #10
0
        public static void ReadObjectIdentifier_FriendlyName(
            PublicEncodingRules ruleSet,
            string inputHex,
            string expectedFriendlyName)
        {
            byte[]    inputData = inputHex.HexToByteArray();
            AsnReader reader    = new AsnReader(inputData, (AsnEncodingRules)ruleSet);

            Oid oid = reader.ReadObjectIdentifier();

            Assert.Equal(expectedFriendlyName, oid.FriendlyName);
        }
コード例 #11
0
        public static void ReadObjectIdentifier_Success(
            AsnEncodingRules ruleSet,
            string inputHex,
            string expectedValue)
        {
            byte[]    inputData = inputHex.HexToByteArray();
            AsnReader reader    = new AsnReader(inputData, ruleSet);

            string oidValue = reader.ReadObjectIdentifier();

            Assert.Equal(expectedValue, oidValue);
        }
コード例 #12
0
 public static string?ReadFromBytes(byte[] data)
 {
     try
     {
         AsnReader reader = new AsnReader(data, AsnEncodingRules.DER);
         return(reader.ReadObjectIdentifier());
     }
     catch (AsnContentException)
     {
         return(null);
     }
 }
コード例 #13
0
        private static void AssertExtension(AsnReader extensions, string oid, bool critical, int index, byte[] bytes)
        {
            AsnReader extension = extensions.ReadSequence();

            Assert.Equal(oid, extension.ReadObjectIdentifier());

            if (critical)
            {
                Assert.True(extension.ReadBoolean(), $"{oid} is critical");
            }

            Assert.True(extension.TryReadPrimitiveOctetString(out ReadOnlyMemory <byte> extensionBytes));
            AssertRefSame(extensionBytes, ref bytes[index], $"{oid} extension value is at byte {index}");
        }
コード例 #14
0
        private static ECParameters ReadParameters(PublicKey publicKey)
        {
            var keySource      = new ReadOnlySpan <byte>(publicKey.EncodedKeyValue.RawData);
            var publicKeyValue = AsnDecoder.ReadOctetString(keySource, AsnEncodingRules.BER, out _);
            var keySize        = publicKeyValue.Length / 2;
            var publicPoint    = new ECPoint
            {
                X = publicKeyValue.Subarray(0, keySize),
                Y = publicKeyValue.Subarray(keySize),
            };

            CryptoUtils.EraseData(ref publicKeyValue);

            var parametersSource = new ReadOnlyMemory <byte>(publicKey.EncodedParameters.RawData);
            var reader           = new AsnReader(parametersSource, AsnEncodingRules.BER);

            reader = reader.ReadSequence();
            var curve = default(ECCurve);

            while (reader.HasData)
            {
                var tag = reader.PeekTag();
                if (tag == Asn1Tag.ObjectIdentifier)
                {
                    var oidValue = reader.ReadObjectIdentifier();
                    if (ECCurveOidMap.OidValueRegistered(oidValue))
                    {
                        curve = ECCurve.CreateFromValue(oidValue);
                        continue;
                    }
                    else if (oidValue == CryptoConstants.Streebog256OidValue || oidValue == CryptoConstants.Streebog512OidValue)
                    {
                        continue;
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }
                else
                {
                    throw new NotImplementedException();
                }
            }

            return(new ECParameters {
                Curve = curve, Q = publicPoint
            });
        }
コード例 #15
0
            public DigestAlgorithmIdentifier(AsnReader asnReader)
            {
                asnReader      = asnReader.ReadSequence();
                this.algorithm = asnReader.ReadObjectIdentifier();
                if (asnReader.PeekTag() == Asn1Tag.Null)
                {
                    asnReader.ReadNull();
                    this.parameters = null;
                }
                else
                {
                    this.parameters = asnReader.ReadEncodedValue().ToArray();
                };

                asnReader.ThrowIfNotEmpty();
            }
コード例 #16
0
        private static IEnumerable <KeyValuePair <string, string> > ReadReverseRdns(X500DistinguishedName name)
        {
            Stack <AsnReader> rdnReaders;

            try
            {
                AsnReader x500NameReader = new AsnReader(name.RawData, AsnEncodingRules.DER);
                AsnReader sequenceReader = x500NameReader.ReadSequence();
                x500NameReader.ThrowIfNotEmpty();
                rdnReaders = new Stack <AsnReader>();

                while (sequenceReader.HasData)
                {
                    rdnReaders.Push(sequenceReader.ReadSetOf());
                }
            }
            catch (AsnContentException e)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
            }

            while (rdnReaders.Count > 0)
            {
                AsnReader rdnReader = rdnReaders.Pop();
                while (rdnReader.HasData)
                {
                    string oid;
                    string value;

                    try
                    {
                        AsnReader tavReader = rdnReader.ReadSequence();
                        oid   = tavReader.ReadObjectIdentifier();
                        value = tavReader.ReadAnyAsnString();
                        tavReader.ThrowIfNotEmpty();
                    }
                    catch (AsnContentException e)
                    {
                        throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
                    }

                    yield return(new KeyValuePair <string, string>(oid, value));
                }
            }
        }
コード例 #17
0
        // More!
        public static void AlgorithmIdentifier_ECC_WithCurves(
            PublicEncodingRules ruleSet,
            string inputHex,
            string curveOid)
        {
            byte[] inputData = inputHex.HexToByteArray();

            var algorithmIdentifier = AsnSerializer.Deserialize <AlgorithmIdentifier>(
                inputData,
                (AsnEncodingRules)ruleSet);

            Assert.Equal("1.2.840.10045.2.1", algorithmIdentifier.Algorithm.Value);

            var reader  = new AsnReader(algorithmIdentifier.Parameters, (AsnEncodingRules)ruleSet);
            Oid curveId = reader.ReadObjectIdentifier(skipFriendlyName: true);

            Assert.Equal(curveOid, curveId.Value);
        }
コード例 #18
0
        public virtual void DecodeX509EnhancedKeyUsageExtension(byte[] encoded, out OidCollection usages)
        {
            // https://tools.ietf.org/html/rfc5924#section-4.1
            //
            // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
            //
            // KeyPurposeId ::= OBJECT IDENTIFIER

            AsnReader reader         = new AsnReader(encoded, AsnEncodingRules.BER);
            AsnReader sequenceReader = reader.ReadSequence();

            reader.ThrowIfNotEmpty();
            usages = new OidCollection();
            while (sequenceReader.HasData)
            {
                usages.Add(sequenceReader.ReadObjectIdentifier());
            }
        }
コード例 #19
0
        internal static void Decode <T>(AsnReader reader, Asn1Tag expectedTag, out T decoded)
            where T : KrbAlgorithmIdentifier, new()
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            decoded = new T();

            AsnReader sequenceReader = reader.ReadSequence(expectedTag);

            decoded.Algorithm = sequenceReader.ReadObjectIdentifier();

            if (sequenceReader.HasData)
            {
                decoded.Parameters = sequenceReader.ReadEncodedValue();
            }

            sequenceReader.ThrowIfNotEmpty();
        }
コード例 #20
0
        public static void ExpectedTag_IgnoresConstructed(
            AsnEncodingRules ruleSet,
            string inputHex,
            TagClass tagClass,
            int tagValue)
        {
            byte[]    inputData      = inputHex.HexToByteArray();
            Asn1Tag   constructedTag = new Asn1Tag(tagClass, tagValue, true);
            Asn1Tag   primitiveTag   = new Asn1Tag(tagClass, tagValue, false);
            AsnReader reader         = new AsnReader(inputData, ruleSet);

            string val1 = reader.ReadObjectIdentifier(constructedTag);

            Assert.False(reader.HasData);

            reader = new AsnReader(inputData, ruleSet);

            string val2 = reader.ReadObjectIdentifier(primitiveTag);

            Assert.False(reader.HasData);

            Assert.Equal(val1, val2);
        }
コード例 #21
0
        private static ISet <string> ReadExtendedKeyUsageExtension(byte[] rawData)
        {
            HashSet <string> oids = new HashSet <string>();

            try
            {
                AsnReader reader         = new AsnReader(rawData, AsnEncodingRules.DER);
                AsnReader sequenceReader = reader.ReadSequence();
                reader.ThrowIfNotEmpty();

                //OidCollection usages
                while (sequenceReader.HasData)
                {
                    oids.Add(sequenceReader.ReadObjectIdentifier());
                }
            }
            catch (AsnContentException e)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
            }

            return(oids);
        }
コード例 #22
0
        private static void AssertRdn(
            AsnReader reader,
            string atvOid,
            int offset,
            Asn1Tag valueTag,
            byte[] bytes,
            string label,
            string stringValue = null)
        {
            AsnReader rdn = reader.ReadSetOf();
            AsnReader attributeTypeAndValue = rdn.ReadSequence();

            Assert.Equal(atvOid, attributeTypeAndValue.ReadObjectIdentifier());

            ReadOnlyMemory <byte> value     = attributeTypeAndValue.ReadEncodedValue();
            ReadOnlySpan <byte>   valueSpan = value.Span;

            Assert.True(Asn1Tag.TryDecode(valueSpan, out Asn1Tag actualTag, out int bytesRead));
            Assert.Equal(1, bytesRead);
            Assert.Equal(valueTag, actualTag);

            AssertRefSame(
                ref MemoryMarshal.GetReference(valueSpan),
                ref bytes[offset],
                $"{label} is at bytes[{offset}]");

            if (stringValue != null)
            {
                AsnReader valueReader = new AsnReader(value, AsnEncodingRules.DER);
                Assert.Equal(stringValue, valueReader.ReadCharacterString((UniversalTagNumber)valueTag.TagValue));
                Assert.False(valueReader.HasData, "valueReader.HasData");
            }

            Assert.False(attributeTypeAndValue.HasData, $"attributeTypeAndValue.HasData ({label})");
            Assert.False(rdn.HasData, $"rdn.HasData ({label})");
        }
コード例 #23
0
        private static string X500DistinguishedNameDecode(
            byte[] encodedName,
            bool printOid,
            bool reverse,
            bool quoteIfNeeded,
            string dnSeparator,
            string multiValueSeparator,
            bool addTrailingDelimiter)
        {
            try
            {
                AsnReader x500NameReader         = new AsnReader(encodedName, AsnEncodingRules.DER);
                AsnReader x500NameSequenceReader = x500NameReader.ReadSequence();
                var       rdnReaders             = new List <AsnReader>();

                x500NameReader.ThrowIfNotEmpty();

                while (x500NameSequenceReader.HasData)
                {
                    // To match Windows' behavior, permit multi-value RDN SETs to not
                    // be DER sorted.
                    rdnReaders.Add(x500NameSequenceReader.ReadSetOf(skipSortOrderValidation: true));
                }

                // We need to allocate a StringBuilder to hold the data as we're building it, and there's the usual
                // arbitrary process of choosing a number that's "big enough" to minimize reallocations without wasting
                // too much space in the average case.
                //
                // So, let's look at an example of what our output might be.
                //
                // GitHub.com's SSL cert has a "pretty long" subject (partially due to the unknown OIDs):
                //   businessCategory=Private Organization
                //   1.3.6.1.4.1.311.60.2.1.3=US
                //   1.3.6.1.4.1.311.60.2.1.2=Delaware
                //   serialNumber=5157550
                //   street=548 4th Street
                //   postalCode=94107
                //   C=US
                //   ST=California
                //   L=San Francisco
                //   O=GitHub, Inc.
                //   CN=github.com
                //
                // Which comes out to 228 characters using OpenSSL's default pretty-print
                // (openssl x509 -in github.cer -text -noout)
                // Throw in some "maybe-I-need-to-quote-this" quotes, and a couple of extra/extra-long O/OU values
                // and round that up to the next programmer number, and you get that 512 should avoid reallocations
                // in all but the most dire of cases.
                StringBuilder decodedName  = new StringBuilder(512);
                int           entryCount   = rdnReaders.Count;
                bool          printSpacing = false;

                for (int i = 0; i < entryCount; i++)
                {
                    int loc = reverse ? entryCount - i - 1 : i;

                    // RelativeDistinguishedName ::=
                    //   SET SIZE (1..MAX) OF AttributeTypeAndValue
                    //
                    // AttributeTypeAndValue::= SEQUENCE {
                    //   type AttributeType,
                    //   value    AttributeValue }
                    //
                    // AttributeType::= OBJECT IDENTIFIER
                    //
                    // AttributeValue ::= ANY-- DEFINED BY AttributeType

                    if (printSpacing)
                    {
                        decodedName.Append(dnSeparator);
                    }
                    else
                    {
                        printSpacing = true;
                    }

                    AsnReader rdnReader = rdnReaders[loc];
                    bool      hadValue  = false;

                    while (rdnReader.HasData)
                    {
                        AsnReader tavReader      = rdnReader.ReadSequence();
                        string    oid            = tavReader.ReadObjectIdentifier();
                        string    attributeValue = tavReader.ReadAnyAsnString();

                        tavReader.ThrowIfNotEmpty();

                        if (hadValue)
                        {
                            decodedName.Append(multiValueSeparator);
                        }
                        else
                        {
                            hadValue = true;
                        }

                        if (printOid)
                        {
                            AppendOid(decodedName, oid);
                        }

                        bool quote = quoteIfNeeded && NeedsQuoting(attributeValue);

                        if (quote)
                        {
                            decodedName.Append('"');

                            // If the RDN itself had a quote within it, that quote needs to be escaped
                            // with another quote.
                            attributeValue = attributeValue.Replace("\"", "\"\"");
                        }

                        decodedName.Append(attributeValue);

                        if (quote)
                        {
                            decodedName.Append('"');
                        }
                    }
                }

                if (addTrailingDelimiter && decodedName.Length > 0)
                {
                    decodedName.Append(dnSeparator);
                }

                return(decodedName.ToString());
            }
            catch (AsnContentException e)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
            }
        }
コード例 #24
0
        public byte[]? GetOutgoingBlob(byte[]?incomingBlob)
        {
            if (_spnegoMechList == null && incomingBlob.AsSpan().StartsWith(NtlmHeader))
            {
                _ntlmPassthrough = true;
                // Windows often sends pure NTLM instead of proper Negotiate, handle that as passthrough
                byte[]? outgoingBlob = _ntlmServer.GetOutgoingBlob(incomingBlob);
                IsAuthenticated      = _ntlmServer.IsAuthenticated;
                return(outgoingBlob);
            }

            Assert.False(_ntlmPassthrough);

            AsnReader reader = new AsnReader(incomingBlob, AsnEncodingRules.DER);

            if (_spnegoMechList == null)
            {
                AsnReader initialContextTokenReader = reader.ReadSequence(new Asn1Tag(TagClass.Application, 0));

                string spNegoOid = initialContextTokenReader.ReadObjectIdentifier();
                Assert.Equal(SpnegoOid, spNegoOid);

                AsnReader negTokenInitReader   = initialContextTokenReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegotiationToken.NegTokenInit)).ReadSequence();
                AsnReader mechTypesOuterReader = negTokenInitReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenInit.MechTypes));
                _spnegoMechList = mechTypesOuterReader.PeekEncodedValue().ToArray();

                bool      hasNtlm         = false;
                bool      isNtlmPreferred = false;
                bool      first           = true;
                AsnReader mechTypesReader = mechTypesOuterReader.ReadSequence();
                while (mechTypesReader.HasData)
                {
                    string mechType = mechTypesReader.ReadObjectIdentifier();
                    if (mechType == NtlmOid)
                    {
                        hasNtlm         = true;
                        isNtlmPreferred = first;
                    }
                    first = false;
                }

                // Skip context flags, if present
                if (negTokenInitReader.HasData && negTokenInitReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenInit.ReqFlags)))
                {
                    negTokenInitReader.ReadSequence();
                }

                byte[]? mechToken = null;
                if (negTokenInitReader.HasData && negTokenInitReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenInit.MechToken)))
                {
                    AsnReader mechTokenReader = negTokenInitReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenInit.MechToken));
                    mechToken = mechTokenReader.ReadOctetString();
                    Assert.False(mechTokenReader.HasData);
                }

                byte[]? mechListMIC = null;
                if (negTokenInitReader.HasData && negTokenInitReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenInit.MechListMIC)))
                {
                    AsnReader mechListMICReader = negTokenInitReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenInit.MechListMIC));
                    mechListMIC = mechListMICReader.ReadOctetString();
                    Assert.False(mechListMICReader.HasData);
                }

                Assert.True(hasNtlm);

                // If the preferred mechanism was NTLM then proceed with the given token
                byte[]? outgoingBlob = null;
                if (isNtlmPreferred && mechToken != null)
                {
                    Assert.Null(mechListMIC);
                    outgoingBlob = _ntlmServer.GetOutgoingBlob(mechToken);
                }

                // Generate reply
                AsnWriter writer = new AsnWriter(AsnEncodingRules.DER);
                using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegotiationToken.NegTokenResp)))
                {
                    using (writer.PushSequence())
                    {
                        using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.NegState)))
                        {
                            if (RequestMIC)
                            {
                                writer.WriteEnumeratedValue(NegState.RequestMic);
                            }
                            else
                            {
                                writer.WriteEnumeratedValue(NegState.AcceptIncomplete);
                            }
                        }

                        using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.SupportedMech)))
                        {
                            writer.WriteObjectIdentifier(NtlmOid);
                        }

                        if (outgoingBlob != null)
                        {
                            using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.ResponseToken)))
                            {
                                writer.WriteOctetString(outgoingBlob);
                            }
                        }
                    }
                }

                return(writer.Encode());
            }
            else
            {
                AsnReader negTokenRespReader = reader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegotiationToken.NegTokenResp)).ReadSequence();

                Assert.True(negTokenRespReader.HasData);
                NegState?clientState;
                if (negTokenRespReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.NegState)))
                {
                    AsnReader valueReader = negTokenRespReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.NegState));
                    clientState = valueReader.ReadEnumeratedValue <NegState>();
                    Assert.False(valueReader.HasData);

                    Assert.NotEqual(NegState.Reject, clientState);
                    Assert.NotEqual(NegState.RequestMic, clientState);
                }

                // Client should not send mechanism
                Assert.False(negTokenRespReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.SupportedMech)));

                byte[]? mechToken = null;
                if (negTokenRespReader.HasData && negTokenRespReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.ResponseToken)))
                {
                    AsnReader mechTokenReader = negTokenRespReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.ResponseToken));
                    mechToken = mechTokenReader.ReadOctetString();
                    Assert.False(mechTokenReader.HasData);
                }

                byte[]? mechListMIC = null;
                if (negTokenRespReader.HasData && negTokenRespReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.MechListMIC)))
                {
                    AsnReader mechListMICReader = negTokenRespReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.MechListMIC));
                    mechListMIC = mechListMICReader.ReadOctetString();
                    Assert.False(mechListMICReader.HasData);
                }

                Assert.NotNull(mechToken);
                byte[]? outgoingBlob = _ntlmServer.GetOutgoingBlob(mechToken);

                if (_ntlmServer.IsAuthenticated)
                {
                    if (RequestMIC)
                    {
                        Assert.NotNull(mechListMIC);
                    }

                    // Validate mechListMIC, if present
                    if (mechListMIC is not null)
                    {
                        _ntlmServer.VerifyMIC(_spnegoMechList, mechListMIC);
                    }
                }
                else
                {
                    Assert.Null(mechListMIC);
                }

                // Generate reply
                AsnWriter writer = new AsnWriter(AsnEncodingRules.DER);
                using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegotiationToken.NegTokenResp)))
                {
                    using (writer.PushSequence())
                    {
                        using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.NegState)))
                        {
                            if (_ntlmServer.IsAuthenticated)
                            {
                                writer.WriteEnumeratedValue(NegState.AcceptCompleted);
                            }
                            else if (outgoingBlob != null)
                            {
                                writer.WriteEnumeratedValue(NegState.AcceptIncomplete);
                            }
                            else
                            {
                                writer.WriteEnumeratedValue(NegState.Reject);
                            }
                        }

                        if (outgoingBlob != null)
                        {
                            using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.ResponseToken)))
                            {
                                writer.WriteOctetString(outgoingBlob);
                            }
                        }

                        if (mechListMIC != null)
                        {
                            using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.MechListMIC)))
                            {
                                Span <byte> mic = stackalloc byte[16];
                                _ntlmServer.GetMIC(_spnegoMechList, mic);
                                writer.WriteOctetString(mic);

                                // MS-SPNG section 3.2.5.1 NTLM RC4 Key State for MechListMIC and First Signed Message
                                // specifies that the RC4 sealing keys are reset back to the initial state for the
                                // first message.
                                _ntlmServer.ResetKeys();
                            }
                        }
                    }
                }

                IsAuthenticated = _ntlmServer.IsAuthenticated;

                return(writer.Encode());
            }
        }
コード例 #25
0
        internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out Rfc3161TimeStampReq decoded)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            decoded = default;
            AsnReader sequenceReader = reader.ReadSequence(expectedTag);
            AsnReader defaultReader;
            AsnReader collectionReader;


            if (!sequenceReader.TryReadInt32(out decoded.Version))
            {
                sequenceReader.ThrowIfNotEmpty();
            }

            System.Security.Cryptography.Pkcs.Asn1.MessageImprint.Decode(sequenceReader, out decoded.MessageImprint);

            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.ObjectIdentifier))
            {
                decoded.ReqPolicy = sequenceReader.ReadObjectIdentifier();
            }


            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.Integer))
            {
                decoded.Nonce = sequenceReader.ReadIntegerBytes();
            }


            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.Boolean))
            {
                decoded.CertReq = sequenceReader.ReadBoolean();
            }
            else
            {
                defaultReader   = new AsnReader(s_defaultCertReq, AsnEncodingRules.DER);
                decoded.CertReq = defaultReader.ReadBoolean();
            }


            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0)))
            {
                // Decode SEQUENCE OF for Extensions
                {
                    collectionReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 0));
                    var tmpList = new List <System.Security.Cryptography.Asn1.X509ExtensionAsn>();
                    System.Security.Cryptography.Asn1.X509ExtensionAsn tmpItem;

                    while (collectionReader.HasData)
                    {
                        System.Security.Cryptography.Asn1.X509ExtensionAsn.Decode(collectionReader, out tmpItem);
                        tmpList.Add(tmpItem);
                    }

                    decoded.Extensions = tmpList.ToArray();
                }
            }


            sequenceReader.ThrowIfNotEmpty();
        }
コード例 #26
0
        public unsafe string ProcessNegotiateChallenge(string challengeString)
        {
            Console.WriteLine($"ChallengesString {challengeString}");

            NegState state = NegState.Unknown;
            string   mech  = null;

            byte[] blob = null;

            byte[]    data            = Convert.FromBase64String(challengeString);
            AsnReader reader          = new AsnReader(data, AsnEncodingRules.DER);
            AsnReader challengeReader = reader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegotiationToken.NegTokenResp));

            // NegTokenResp::= SEQUENCE {
            //    negState[0] ENUMERATED {
            //        accept - completed(0),
            //        accept - incomplete(1),
            //        reject(2),
            //        request - mic(3)
            //    } OPTIONAL,
            // --REQUIRED in the first reply from the target
            //    supportedMech[1] MechType OPTIONAL,
            // --present only in the first reply from the target
            // responseToken[2] OCTET STRING  OPTIONAL,
            // mechListMIC[3] OCTET STRING  OPTIONAL,
            // ...
            // }

            challengeReader = challengeReader.ReadSequence();
            while (challengeReader.HasData)
            {
                Asn1Tag tag = challengeReader.PeekTag();
                if (tag.TagClass == TagClass.ContextSpecific)
                {
                    NegTokenResp dataType      = (NegTokenResp)tag.TagValue;
                    AsnReader    specificValue = new AsnReader(challengeReader.PeekContentBytes(), AsnEncodingRules.DER);

                    switch (dataType)
                    {
                    case NegTokenResp.NegState:
                        state = specificValue.ReadEnumeratedValue <NegState>();
                        break;

                    case NegTokenResp.SupportedMech:
                        mech = specificValue.ReadObjectIdentifier();
                        break;

                    case NegTokenResp.ResponseToken:
                        blob = specificValue.ReadOctetString();
                        break;

                    default:
                        // Ignore everything else
                        break;
                    }
                }

                challengeReader.ReadEncodedValue();
            }

            if (Diag)
            {
                Console.WriteLine("Negotiate challenege: {0} - {1} in {2}", challengeString, mech, state);
            }

            // Mechanism should be set on first message. That means always
            // as NTLM has only one challenege message.
            if (!NtlmOid.Equals(mech))
            {
                throw new NotSupportedException($"'{mech}' mechanism is not supported");
            }


            if (state != NegState.Unknown && state != NegState.AcceptIncomplete)
            {
                // If state was set, it should be AcceptIncomplete for us to proseed.
                return("");
            }

            if (blob?.Length > 0)
            {
                // Process decoded NTLM blob.
                byte[] response = ProcessChallengeMessage(blob);
                if (response?.Length > 0)
                {
                    AsnWriter writer = new AsnWriter(AsnEncodingRules.DER);

                    using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegotiationToken.NegTokenResp)))
                    {
                        writer.PushSequence();
                        using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenInit.MechToken)))
                        {
                            writer.WriteOctetString(response);
                        }

                        writer.PopSequence();
                    }

                    return("Negotiate " + Convert.ToBase64String(writer.Encode(), Base64FormattingOptions.None));
                }
            }

            return("");
        }
コード例 #27
0
ファイル: Rfc3161TstInfo.xml.cs プロジェクト: pentp/corefx
        internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out Rfc3161TstInfo decoded)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            decoded = default;
            AsnReader sequenceReader = reader.ReadSequence(expectedTag);
            AsnReader explicitReader;
            AsnReader defaultReader;
            AsnReader collectionReader;


            if (!sequenceReader.TryReadInt32(out decoded.Version))
            {
                sequenceReader.ThrowIfNotEmpty();
            }

            decoded.Policy = sequenceReader.ReadObjectIdentifier();
            System.Security.Cryptography.Pkcs.Asn1.MessageImprint.Decode(sequenceReader, out decoded.MessageImprint);
            decoded.SerialNumber = sequenceReader.GetIntegerBytes();
            decoded.GenTime      = sequenceReader.GetGeneralizedTime();

            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.Sequence))
            {
                System.Security.Cryptography.Pkcs.Asn1.Rfc3161Accuracy tmpAccuracy;
                System.Security.Cryptography.Pkcs.Asn1.Rfc3161Accuracy.Decode(sequenceReader, out tmpAccuracy);
                decoded.Accuracy = tmpAccuracy;
            }


            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.Boolean))
            {
                decoded.Ordering = sequenceReader.ReadBoolean();
            }
            else
            {
                defaultReader    = new AsnReader(s_defaultOrdering, AsnEncodingRules.DER);
                decoded.Ordering = defaultReader.ReadBoolean();
            }


            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.Integer))
            {
                decoded.Nonce = sequenceReader.GetIntegerBytes();
            }


            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0)))
            {
                explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 0));
                System.Security.Cryptography.Asn1.GeneralNameAsn tmpTsa;
                System.Security.Cryptography.Asn1.GeneralNameAsn.Decode(explicitReader, out tmpTsa);
                decoded.Tsa = tmpTsa;

                explicitReader.ThrowIfNotEmpty();
            }


            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1)))
            {
                // Decode SEQUENCE OF for Extensions
                {
                    collectionReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 1));
                    var tmpList = new List <System.Security.Cryptography.Asn1.X509ExtensionAsn>();
                    System.Security.Cryptography.Asn1.X509ExtensionAsn tmpItem;

                    while (collectionReader.HasData)
                    {
                        System.Security.Cryptography.Asn1.X509ExtensionAsn.Decode(collectionReader, out tmpItem);
                        tmpList.Add(tmpItem);
                    }

                    decoded.Extensions = tmpList.ToArray();
                }
            }


            sequenceReader.ThrowIfNotEmpty();
        }
コード例 #28
0
        public static void ReadMicrosoftComCert()
        {
            byte[]    bytes      = MicrosoftDotComSslCertBytes;
            AsnReader fileReader = new AsnReader(bytes, AsnEncodingRules.DER);

            AsnReader certReader = fileReader.ReadSequence();

            Assert.False(fileReader.HasData, "fileReader.HasData");

            AsnReader tbsCertReader = certReader.ReadSequence();
            AsnReader sigAlgReader  = certReader.ReadSequence();

            Assert.True(
                certReader.TryReadPrimitiveBitString(
                    out int unusedBitCount,
                    out ReadOnlyMemory <byte> signature),
                "certReader.TryReadPrimitiveBitStringValue");

            Assert.Equal(0, unusedBitCount);
            AssertRefSame(signature, ref bytes[1176], "Signature is a ref to bytes[1176]");

            Assert.False(certReader.HasData, "certReader.HasData");

            AsnReader versionExplicitWrapper = tbsCertReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 0));

            Assert.True(versionExplicitWrapper.TryReadInt32(out int certVersion));
            Assert.Equal(2, certVersion);
            Assert.False(versionExplicitWrapper.HasData, "versionExplicitWrapper.HasData");

            ReadOnlyMemory <byte> serialBytes = tbsCertReader.ReadIntegerBytes();

            AssertRefSame(serialBytes, ref bytes[15], "Serial number starts at bytes[15]");

            AsnReader tbsSigAlgReader = tbsCertReader.ReadSequence();

            Assert.Equal("1.2.840.113549.1.1.11", tbsSigAlgReader.ReadObjectIdentifier());
            Assert.True(tbsSigAlgReader.HasData, "tbsSigAlgReader.HasData before ReadNull");
            tbsSigAlgReader.ReadNull();
            Assert.False(tbsSigAlgReader.HasData, "tbsSigAlgReader.HasData after ReadNull");

            AsnReader issuerReader    = tbsCertReader.ReadSequence();
            Asn1Tag   printableString = new Asn1Tag(UniversalTagNumber.PrintableString);

            AssertRdn(issuerReader, "2.5.4.6", 57, printableString, bytes, "issuer[C]");
            AssertRdn(issuerReader, "2.5.4.10", 70, printableString, bytes, "issuer[O]");
            AssertRdn(issuerReader, "2.5.4.11", 101, printableString, bytes, "issuer[OU]");
            AssertRdn(issuerReader, "2.5.4.3", 134, printableString, bytes, "issuer[CN]");
            Assert.False(issuerReader.HasData, "issuerReader.HasData");

            AsnReader validityReader = tbsCertReader.ReadSequence();

            Assert.Equal(new DateTimeOffset(2014, 10, 15, 0, 0, 0, TimeSpan.Zero), validityReader.ReadUtcTime());
            Assert.Equal(new DateTimeOffset(2016, 10, 15, 23, 59, 59, TimeSpan.Zero), validityReader.ReadUtcTime());
            Assert.False(validityReader.HasData, "validityReader.HasData");

            AsnReader subjectReader = tbsCertReader.ReadSequence();
            Asn1Tag   utf8String    = new Asn1Tag(UniversalTagNumber.UTF8String);

            AssertRdn(subjectReader, "1.3.6.1.4.1.311.60.2.1.3", 220, printableString, bytes, "subject[EV Country]");
            AssertRdn(subjectReader, "1.3.6.1.4.1.311.60.2.1.2", 241, utf8String, bytes, "subject[EV State]", "Washington");
            AssertRdn(subjectReader, "2.5.4.15", 262, printableString, bytes, "subject[Business Category]");
            AssertRdn(subjectReader, "2.5.4.5", 293, printableString, bytes, "subject[Serial Number]");
            AssertRdn(subjectReader, "2.5.4.6", 313, printableString, bytes, "subject[C]");
            AssertRdn(subjectReader, "2.5.4.17", 326, utf8String, bytes, "subject[Postal Code]", "98052");
            AssertRdn(subjectReader, "2.5.4.8", 342, utf8String, bytes, "subject[ST]", "Washington");
            AssertRdn(subjectReader, "2.5.4.7", 363, utf8String, bytes, "subject[L]", "Redmond");
            AssertRdn(subjectReader, "2.5.4.9", 381, utf8String, bytes, "subject[Street Address]", "1 Microsoft Way");
            AssertRdn(subjectReader, "2.5.4.10", 407, utf8String, bytes, "subject[O]", "Microsoft Corporation");
            AssertRdn(subjectReader, "2.5.4.11", 439, utf8String, bytes, "subject[OU]", "MSCOM");
            AssertRdn(subjectReader, "2.5.4.3", 455, utf8String, bytes, "subject[CN]", "www.microsoft.com");
            Assert.False(subjectReader.HasData, "subjectReader.HasData");

            AsnReader subjectPublicKeyInfo = tbsCertReader.ReadSequence();
            AsnReader spkiAlgorithm        = subjectPublicKeyInfo.ReadSequence();

            Assert.Equal("1.2.840.113549.1.1.1", spkiAlgorithm.ReadObjectIdentifier());
            spkiAlgorithm.ReadNull();
            Assert.False(spkiAlgorithm.HasData, "spkiAlgorithm.HasData");

            Assert.True(
                subjectPublicKeyInfo.TryReadPrimitiveBitString(
                    out unusedBitCount,
                    out ReadOnlyMemory <byte> encodedPublicKey),
                "subjectPublicKeyInfo.TryReadBitStringBytes");

            Assert.Equal(0, unusedBitCount);
            AssertRefSame(encodedPublicKey, ref bytes[498], "Encoded public key starts at byte 498");

            Assert.False(subjectPublicKeyInfo.HasData, "subjectPublicKeyInfo.HasData");

            AsnReader publicKeyReader    = new AsnReader(encodedPublicKey, AsnEncodingRules.DER);
            AsnReader rsaPublicKeyReader = publicKeyReader.ReadSequence();

            AssertRefSame(rsaPublicKeyReader.ReadIntegerBytes(), ref bytes[506], "RSA Modulus is at bytes[502]");
            Assert.True(rsaPublicKeyReader.TryReadInt32(out int rsaExponent));
            Assert.Equal(65537, rsaExponent);
            Assert.False(rsaPublicKeyReader.HasData, "rsaPublicKeyReader.HasData");
            Assert.False(publicKeyReader.HasData, "publicKeyReader.HasData");

            AsnReader extensionsContainer = tbsCertReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 3));
            AsnReader extensions          = extensionsContainer.ReadSequence();

            Assert.False(extensionsContainer.HasData, "extensionsContainer.HasData");

            AsnReader sanExtension = extensions.ReadSequence();

            Assert.Equal("2.5.29.17", sanExtension.ReadObjectIdentifier());
            Assert.True(sanExtension.TryReadPrimitiveOctetString(out ReadOnlyMemory <byte> sanExtensionBytes));
            Assert.False(sanExtension.HasData, "sanExtension.HasData");

            AsnReader sanExtensionPayload = new AsnReader(sanExtensionBytes, AsnEncodingRules.DER);
            AsnReader sanExtensionValue   = sanExtensionPayload.ReadSequence();

            Assert.False(sanExtensionPayload.HasData, "sanExtensionPayload.HasData");
            Asn1Tag dnsName = new Asn1Tag(TagClass.ContextSpecific, 2);

            Assert.Equal("www.microsoft.com", sanExtensionValue.ReadCharacterString(UniversalTagNumber.IA5String, dnsName));
            Assert.Equal("wwwqa.microsoft.com", sanExtensionValue.ReadCharacterString(UniversalTagNumber.IA5String, dnsName));
            Assert.False(sanExtensionValue.HasData, "sanExtensionValue.HasData");

            AsnReader basicConstraints = extensions.ReadSequence();

            Assert.Equal("2.5.29.19", basicConstraints.ReadObjectIdentifier());
            Assert.True(basicConstraints.TryReadPrimitiveOctetString(out ReadOnlyMemory <byte> basicConstraintsBytes));

            AsnReader basicConstraintsPayload = new AsnReader(basicConstraintsBytes, AsnEncodingRules.DER);
            AsnReader basicConstraintsValue   = basicConstraintsPayload.ReadSequence();

            Assert.False(basicConstraintsValue.HasData, "basicConstraintsValue.HasData");
            Assert.False(basicConstraintsPayload.HasData, "basicConstraintsPayload.HasData");

            AsnReader keyUsageExtension = extensions.ReadSequence();

            Assert.Equal("2.5.29.15", keyUsageExtension.ReadObjectIdentifier());
            Assert.True(keyUsageExtension.ReadBoolean(), "keyUsageExtension.ReadBoolean() (IsCritical)");
            Assert.True(keyUsageExtension.TryReadPrimitiveOctetString(out ReadOnlyMemory <byte> keyUsageBytes));

            AsnReader keyUsagePayload = new AsnReader(keyUsageBytes, AsnEncodingRules.DER);

            Assert.Equal(
                X509KeyUsageCSharpStyle.DigitalSignature | X509KeyUsageCSharpStyle.KeyEncipherment,
                keyUsagePayload.ReadNamedBitListValue <X509KeyUsageCSharpStyle>());

            Assert.False(keyUsagePayload.HasData, "keyUsagePayload.HasData");

            AssertExtension(extensions, "2.5.29.37", false, 863, bytes);
            AssertExtension(extensions, "2.5.29.32", false, 894, bytes);
            AssertExtension(extensions, "2.5.29.35", false, 998, bytes);
            AssertExtension(extensions, "2.5.29.31", false, 1031, bytes);
            AssertExtension(extensions, "1.3.6.1.5.5.7.1.1", false, 1081, bytes);
            Assert.False(extensions.HasData, "extensions.HasData");

            Assert.Equal("1.2.840.113549.1.1.11", sigAlgReader.ReadObjectIdentifier());
            sigAlgReader.ReadNull();
            Assert.False(sigAlgReader.HasData);
        }