Esempio n. 1
0
        public static void TryCopyBitStringBytes_ExtremelyNested()
        {
            byte[] dataBytes = new byte[4 * 16384];

            // This will build 2^14 nested indefinite length values.
            // In the end, none of them contain any content.
            //
            // For what it's worth, the initial algorithm succeeded at 1017, and StackOverflowed with 1018.
            int end = dataBytes.Length / 2;

            // UNIVERSAL BIT STRING [Constructed]
            const byte Tag = 0x20 | (byte)UniversalTagNumber.BitString;

            for (int i = 0; i < end; i += 2)
            {
                dataBytes[i] = Tag;
                // Indefinite length
                dataBytes[i + 1] = 0x80;
            }

            AsnReader reader = new AsnReader(dataBytes, AsnEncodingRules.BER);

            int bytesWritten;
            int unusedBitCount;

            Assert.True(
                reader.TryCopyBitStringBytes(Span <byte> .Empty, out unusedBitCount, out bytesWritten));

            Assert.Equal(0, bytesWritten);
            Assert.Equal(0, unusedBitCount);
        }
Esempio n. 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);
        }
Esempio n. 3
0
        public static void TryCopyBitStringBytes_Fails(PublicEncodingRules ruleSet, string inputHex)
        {
            byte[]    inputData = inputHex.HexToByteArray();
            AsnReader reader    = new AsnReader(inputData, (AsnEncodingRules)ruleSet);

            bool didRead = reader.TryCopyBitStringBytes(
                Span <byte> .Empty,
                out int unusedBitCount,
                out int bytesWritten);

            Assert.False(didRead, "reader.TryCopyBitStringBytes");
            Assert.Equal(0, unusedBitCount);
            Assert.Equal(0, bytesWritten);
        }
Esempio n. 4
0
        private static void TryCopyBitStringBytes_Throws_Helper(
            PublicEncodingRules ruleSet,
            byte[] input)
        {
            AsnReader reader = new AsnReader(input, (AsnEncodingRules)ruleSet);

            Assert.Throws <CryptographicException>(
                () =>
            {
                reader.TryCopyBitStringBytes(
                    Span <byte> .Empty,
                    out int unusedBitCount,
                    out int bytesWritten);
            });
        }
Esempio n. 5
0
        public static void TryCopyBitStringBytes_Success(
            PublicEncodingRules ruleSet,
            string inputHex,
            string expectedHex,
            int expectedUnusedBitCount)
        {
            byte[]    inputData = inputHex.HexToByteArray();
            byte[]    output    = new byte[expectedHex.Length / 2];
            AsnReader reader    = new AsnReader(inputData, (AsnEncodingRules)ruleSet);

            bool didRead = reader.TryCopyBitStringBytes(
                output,
                out int unusedBitCount,
                out int bytesWritten);

            Assert.True(didRead, "reader.TryCopyBitStringBytes");
            Assert.Equal(expectedUnusedBitCount, unusedBitCount);
            Assert.Equal(expectedHex, output.AsSpan(0, bytesWritten).ByteArrayToHex());
        }
Esempio n. 6
0
        public static void TryCopyBitStringBytes_Success_CER_MaxPrimitiveLength()
        {
            // CER says that the maximum encoding length for a BitString primitive is
            // 1000 (999 value bytes and 1 unused bit count byte).
            //
            // So we need 03 [1000] [0x00-0x07] { 998 anythings } [a byte that's legal for the bitmask]
            // 1000 => 0x3E8, so the length encoding is 82 03 E8.
            // 1000 + 3 + 1 == 1003
            byte[] input = new byte[1004];
            input[0] = 0x03;
            input[1] = 0x82;
            input[2] = 0x03;
            input[3] = 0xE8;

            // Unused bits
            input[4] = 0x02;

            // Payload
            input[5]    = 0xA0;
            input[1002] = 0xA5;
            input[1003] = 0xFC;

            byte[] output = new byte[999];

            AsnReader reader = new AsnReader(input, AsnEncodingRules.CER);

            bool success = reader.TryCopyBitStringBytes(
                output,
                out int unusedBitCount,
                out int bytesWritten);

            Assert.True(success, "reader.TryCopyBitStringBytes");
            Assert.Equal(input[4], unusedBitCount);
            Assert.Equal(999, bytesWritten);

            Assert.Equal(
                input.AsSpan(5).ByteArrayToHex(),
                output.ByteArrayToHex());
        }
Esempio n. 7
0
        public static void TryCopyBitStringBytes_Success_CER_MinConstructedLength()
        {
            // CER says that the maximum encoding length for a BitString primitive is
            // 1000 (999 value bytes and 1 unused bit count byte), and that a constructed
            // form must be used for values greater than 1000 bytes, with segments dividing
            // up for each thousand [1000, 1000, ..., len%1000].
            //
            // Bit string primitives are one byte of "unused bits" and the rest are payload,
            // so the minimum constructed payload has total content length 1002:
            // [1000 (1+999), 2 (1+1)]
            //
            // 23 80 (indefinite constructed bit string)
            //    03 82 03 E9 (primitive bit string, 1000 bytes)
            //       00 [999 more payload bytes]
            //    03 02 (primitive bit string, 2 bytes)
            //       uu pp
            //    00 00 (end of contents, 0 bytes)
            // 1010 total.
            byte[] input  = new byte[1012];
            int    offset = 0;

            // CONSTRUCTED BIT STRING (Indefinite)
            input[offset++] = 0x23;
            input[offset++] = 0x80;
            // BIT STRING (1000)
            input[offset++] = 0x03;
            input[offset++] = 0x82;
            input[offset++] = 0x03;
            input[offset++] = 0xE8;

            // Primitive 1: Unused bits MUST be 0.
            input[offset++] = 0x00;

            // Payload (A0 :: A5 FC) (999)
            input[offset]   = 0xA0;
            offset         += 997;
            input[offset++] = 0xA5;
            input[offset++] = 0xFC;

            // BIT STRING (2)
            input[offset++] = 0x03;
            input[offset++] = 0x02;

            // Primitive 2: Unused bits 0-7
            input[offset++] = 0x3;

            // Payload (must have the three least significant bits unset)
            input[offset] = 0b0000_1000;

            byte[] expected = new byte[1000];
            offset             = 0;
            expected[offset]   = 0xA0;
            offset            += 997;
            expected[offset++] = 0xA5;
            expected[offset++] = 0xFC;
            expected[offset]   = 0b0000_1000;

            byte[] output = new byte[1000];

            AsnReader reader = new AsnReader(input, AsnEncodingRules.CER);

            bool success = reader.TryCopyBitStringBytes(
                output,
                out int unusedBitCount,
                out int bytesWritten);

            Assert.True(success, "reader.TryCopyBitStringBytes");
            Assert.Equal(input[1006], unusedBitCount);
            Assert.Equal(1000, bytesWritten);

            Assert.Equal(
                expected.ByteArrayToHex(),
                output.ByteArrayToHex());
        }