public void EncodeAllUnicodeCodePoints(bool useUtf8Encoder)
        {
            TextEncoder encoder = useUtf8Encoder ? TextEncoder.Utf8 : TextEncoder.Utf16;

            Text.Encoding systemEncoder         = useUtf8Encoder ? Text.Encoding.UTF8 : Text.Encoding.Unicode;
            const uint    maximumValidCodePoint = 0x10FFFF;

            uint[] codePoints = new uint[maximumValidCodePoint + 1];

            var plainText = new StringBuilder();

            for (int i = 0; i <= maximumValidCodePoint; i++)
            {
                if (i >= 0xD800 && i <= 0xDFFF)
                {
                    codePoints[i] = 0;         // skip surrogate characters
                    plainText.Append((char)0); // skip surrogate characters
                }
                else
                {
                    codePoints[i] = (uint)i;

                    if (i > 0xFFFF)
                    {
                        plainText.Append(char.ConvertFromUtf32(i));
                    }
                    else
                    {
                        plainText.Append((char)i);
                    }
                }
            }

            ReadOnlySpan <uint> codePointsSpan = new ReadOnlySpan <uint>(codePoints);
            uint        maxBytes = 4 * (maximumValidCodePoint + 1);
            Span <byte> buffer   = new Span <byte>(new byte[maxBytes]);
            int         bytesWritten;
            int         consumed;

            Assert.True(encoder.TryEncode(codePointsSpan, buffer, out consumed, out bytesWritten));

            string unicodeString           = plainText.ToString();
            ReadOnlySpan <char> characters = unicodeString.AsSpan();
            int byteCount = systemEncoder.GetByteCount(unicodeString);

            byte[]      buff = new byte[byteCount];
            Span <byte> expectedBuffer;

            char[] charArray = characters.ToArray();

            systemEncoder.GetBytes(charArray, 0, characters.Length, buff, 0);
            expectedBuffer = new Span <byte>(buff);

            int minLength = Math.Min(expectedBuffer.Length, buffer.Length);

            for (int i = 0; i < minLength; i++)
            {
                Assert.Equal(expectedBuffer[i], buffer[i]);
            }
        }
Exemple #2
0
        /// <summary>
        ///   Write the provided string using the specified encoding type using the specified
        ///   tag corresponding to the encoding type.
        /// </summary>
        /// <param name="tag">The tag to write.</param>
        /// <param name="encodingType">
        ///   The <see cref="UniversalTagNumber"/> corresponding to the encoding to use.
        /// </param>
        /// <param name="str">The string to write.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///   <paramref name="encodingType"/> is not a restricted character string encoding type --OR--
        ///   <paramref name="encodingType"/> is a restricted character string encoding type that is not
        ///   currently supported by this method
        /// </exception>
        /// <exception cref="ArgumentException">
        ///   <paramref name="tag"/>.<see cref="Asn1Tag.TagClass"/> is
        ///   <see cref="TagClass.Universal"/>, but
        ///   <paramref name="tag"/>.<see cref="Asn1Tag.TagValue"/> is not correct for
        ///   the method
        /// </exception>
        /// <exception cref="ObjectDisposedException">The writer has been Disposed.</exception>
        public void WriteCharacterString(Asn1Tag tag, UniversalTagNumber encodingType, ReadOnlySpan <char> str)
        {
            CheckUniversalTag(tag, encodingType);

            Text.Encoding encoding = AsnCharacterStringEncodings.GetEncoding(encodingType);
            this.WriteCharacterStringCore(tag, encoding, str);
        }
Exemple #3
0
 public static ICharacterDevice Wrap(IByteDevice backend, Text.Encoding encoding)
 {
     return(backend.NotNull() ? new CharacterDevice(backend, encoding)
     {
         dontClose = true
     } : null);
 }
        // T-REC-X.690-201508 sec 8.23
        private void WriteCharacterStringCore(Asn1Tag tag, Text.Encoding encoding, ReadOnlySpan <char> str)
        {
            int size = encoding.GetByteCount(str);

            // T-REC-X.690-201508 sec 9.2
            if (RuleSet == AsnEncodingRules.CER)
            {
                // If it exceeds the primitive segment size, use the constructed encoding.
                if (size > AsnReader.MaxCERSegmentSize)
                {
                    WriteConstructedCerCharacterString(tag, encoding, str, size);
                    return;
                }
            }

            // Clear the constructed tag, if present.
            WriteTag(tag.AsPrimitive());
            WriteLength(size);
            Span <byte> dest = _buffer.AsSpan(_offset, size);

            int written = encoding.GetBytes(str, dest);

            if (written != size)
            {
                Debug.Fail(
                    $"Encoding produced different answer for GetByteCount ({size}) and GetBytes ({written})");
                throw new InvalidOperationException();
            }

            _offset += size;
        }
Exemple #5
0
 CharacterDevice(IByteDevice backend, Text.Encoding encoding)
 {
     this.backend  = backend;
     this.encoding = encoding;
     this.peeked   = new PeekBuffer(async() =>
     {
         // TODO: Could we use this.encoder.Encode(Func<byte?>)?
         char?result = null;
         var next    = await this.backend.Read();
         if (next.HasValue)
         {
             var buffer = new byte[this.encoding.GetSymbolLength(next.Value)];
             buffer[0]  = next.Value;
             for (var i = 1; i < buffer.Length && (next = await this.backend.Read()).HasValue; i++)
             {
                 buffer[i] = next.Value;
             }
             var r = this.encoding.Decode(buffer);
             if (r.Length > 0)
             {
                 result = r[0];
             }
         }
         return(result);
     });
 }
        /// <summary>
        ///   Write the provided string using the specified encoding type using the specified
        ///   tag corresponding to the encoding type.
        /// </summary>
        /// <param name="encodingType">
        ///   One of the enumeration values representing the encoding to use.
        /// </param>
        /// <param name="str">The string to write.</param>
        /// <param name="tag">
        ///   The tag to write, or <see langword="null"/> for the universal tag that is appropriate to
        ///   the requested encoding type.
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///   <paramref name="encodingType"/> is not a restricted character string encoding type.
        ///
        ///   -or-
        ///
        ///   <paramref name="encodingType"/> is a restricted character string encoding type that is not
        ///   currently supported by this method.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///   <paramref name="tag"/>.<see cref="Asn1Tag.TagClass"/> is
        ///   <see cref="TagClass.Universal"/>, but
        ///   <paramref name="tag"/>.<see cref="Asn1Tag.TagValue"/> is not correct for
        ///   the method.
        /// </exception>
        public void WriteCharacterString(UniversalTagNumber encodingType, ReadOnlySpan <char> str, Asn1Tag?tag = null)
        {
            CheckUniversalTag(tag, encodingType);

            Text.Encoding encoding = AsnCharacterStringEncodings.GetEncoding(encodingType);
            WriteCharacterStringCore(tag ?? new Asn1Tag(encodingType), encoding, str);
        }
Exemple #7
0
        private void WriteConstructedCerCharacterString(Asn1Tag tag, Text.Encoding encoding, ReadOnlySpan <char> str, int size)
        {
            Debug.Assert(size > AsnReader.MaxCERSegmentSize);

            byte[] tmp;

            unsafe
            {
                fixed(char *strPtr = &MemoryMarshal.GetReference(str))
                {
                    tmp = CryptoPool.Rent(size);

                    fixed(byte *destPtr = tmp)
                    {
                        int written = encoding.GetBytes(strPtr, str.Length, destPtr, tmp.Length);

                        if (written != size)
                        {
                            Debug.Fail(
                                $"Encoding produced different answer for GetByteCount ({size}) and GetBytes ({written})");
                            throw new InvalidOperationException();
                        }
                    }
                }
            }

            WriteConstructedCerOctetString(tag, tmp.AsSpan(0, size));
            CryptoPool.Return(tmp, size);
        }
Exemple #8
0
        public void EncodeFromUtf8toUtf8UsingTextEncoder(int length, int minCodePoint, int maxCodePoint, SpecialTestCases special = SpecialTestCases.None)
        {
            string inputString = GenerateStringData(length, minCodePoint, maxCodePoint, special);

            char[]        characters     = inputString.AsSpan().ToArray();
            Text.Encoding utf8Encoder    = Text.Encoding.UTF8;
            int           utf8Length     = utf8Encoder.GetByteCount(characters);
            var           utf8TempBuffer = new byte[utf8Length];

            utf8Encoder.GetBytes(characters, 0, characters.Length, utf8TempBuffer, 0);
            Span <byte> utf8Span = new Span <byte>(utf8TempBuffer);

            TextEncoder utf8       = TextEncoder.Utf8;
            var         utf8Buffer = new byte[utf8Length];
            var         span       = new Span <byte>(utf8Buffer);

            foreach (var iteration in Benchmark.Iterations)
            {
                using (iteration.StartMeasurement())
                    for (int i = 0; i < Benchmark.InnerIterationCount; i++)
                    {
                        if (!utf8.TryEncode(utf8Span, span, out int consumed, out int written))
                        {
                            throw new Exception();
                        }
                    }
            }
        }
Exemple #9
0
        public void EncodeFromUtf32toUtf16UsingTextEncoder(int length, int minCodePoint, int maxCodePoint, SpecialTestCases special = SpecialTestCases.None)
        {
            string inputString = GenerateStringData(length, minCodePoint, maxCodePoint, special);

            char[]        characters  = inputString.AsSpan().ToArray();
            Text.Encoding utf32       = Text.Encoding.UTF32;
            int           utf32Length = utf32.GetByteCount(characters);
            var           utf32Buffer = new byte[utf32Length];

            utf32.GetBytes(characters, 0, characters.Length, utf32Buffer, 0);
            Span <byte>         utf32ByteSpan = new Span <byte>(utf32Buffer);
            ReadOnlySpan <uint> utf32Span     = utf32ByteSpan.NonPortableCast <byte, uint>();

            TextEncoder utf16 = TextEncoder.Utf16;

            Assert.True(utf16.TryComputeEncodedBytes(utf32Span, out int encodedBytes));
            var utf16Buffer = new byte[encodedBytes];
            var span        = new Span <byte>(utf16Buffer);

            foreach (var iteration in Benchmark.Iterations)
            {
                using (iteration.StartMeasurement())
                    for (int i = 0; i < Benchmark.InnerIterationCount; i++)
                    {
                        if (!utf16.TryEncode(utf32Span, span, out int consumed, out int written))
                        {
                            throw new Exception();
                        }
                    }
            }
        }
Exemple #10
0
        private void WriteConstructedCerCharacterString(Asn1Tag tag, Text.Encoding encoding, ReadOnlySpan <char> str, int size)
        {
            Debug.Assert(size > AsnReader.MaxCERSegmentSize);

            byte[] tmp;

            // TODO: Split this for netstandard vs netcoreapp for span?.
            var localPool = ArrayPool <byte> .Shared;

            unsafe
            {
                fixed(char *strPtr = &MemoryMarshal.GetReference(str))
                {
                    tmp = localPool.Rent(size);

                    fixed(byte *destPtr = tmp)
                    {
                        int written = encoding.GetBytes(strPtr, str.Length, destPtr, tmp.Length);

                        if (written != size)
                        {
                            Debug.Fail(
                                $"Encoding produced different answer for GetByteCount ({size}) and GetBytes ({written})");
                            throw new InvalidOperationException();
                        }
                    }
                }
            }

            WriteConstructedCerOctetString(tag, tmp.AsSpan(0, size));
            Array.Clear(tmp, 0, size);
            localPool.Return(tmp);
        }
        public void EncodeFromUtf32toUtf8UsingEncoding(int length, int minCodePoint, int maxCodePoint, SpecialTestCases special = SpecialTestCases.None)
        {
            string inputString = GenerateStringData(length, minCodePoint, maxCodePoint, special);

            char[]        characters  = inputString.AsSpan().ToArray();
            Text.Encoding utf32       = Text.Encoding.UTF32;
            Text.Encoding utf8        = Text.Encoding.UTF8;
            int           utf32Length = utf32.GetByteCount(characters);
            var           utf32Buffer = new byte[utf32Length];

            utf32.GetBytes(characters, 0, characters.Length, utf32Buffer, 0);

            int utf8Length = utf8.GetByteCount(characters);
            var utf8Bytes  = new byte[utf8Length];
            var utf16Chars = new char[characters.Length];

            foreach (var iteration in Benchmark.Iterations)
            {
                using (iteration.StartMeasurement())
                    for (int i = 0; i < Benchmark.InnerIterationCount; i++)
                    {
                        utf32.GetChars(utf32Buffer, 0, utf32Buffer.Length, utf16Chars, 0);
                        utf8.GetBytes(utf16Chars, 0, utf16Chars.Length, utf8Bytes, 0);
                    }
            }
        }
        // Checks if the string that gets genereted from the subset of the valid vode points gets encoded correctly
        // by comparing TextEncoder output to the output from Encoding for any of the encodings that TextEncoder supports.
        public static bool Validate(SupportedEncoding from, TextEncoder textEncoder, Text.Encoding testEncoder, CodePointSubset subset)
        {
            string inputString = GenerateValidString(TextEncoderConstants.DataLength, subset);

            Text.Encoding testEncoderUtf8    = Text.Encoding.UTF8;
            Text.Encoding testEncoderUnicode = Text.Encoding.Unicode;
            Text.Encoding testEncoderUtf32   = Text.Encoding.UTF32;

            byte[]      expectedBytes;
            Span <byte> encodedBytes;

            int  bytesWritten;
            bool retVal = true;

            switch (from)
            {
            case SupportedEncoding.FromUtf8:
                byte[] inputStringUtf8 = testEncoderUtf8.GetBytes(inputString);
                expectedBytes = Text.Encoding.Convert(testEncoderUtf8, testEncoder, inputStringUtf8);
                encodedBytes  = new Span <byte>(new byte[expectedBytes.Length]);
                ReadOnlySpan <byte> inputUtf8 = inputStringUtf8;
                retVal &= textEncoder.TryEncode(inputUtf8, encodedBytes, out int charactersConsumed, out bytesWritten);
                retVal &= inputUtf8.Length == charactersConsumed;
                break;

            case SupportedEncoding.FromUtf16:
                byte[] inputStringUtf16 = testEncoderUnicode.GetBytes(inputString);
                expectedBytes = Text.Encoding.Convert(testEncoderUnicode, testEncoder, inputStringUtf16);
                encodedBytes  = new Span <byte>(new byte[expectedBytes.Length]);
                ReadOnlySpan <char> inputUtf16 = inputStringUtf16.AsSpan().NonPortableCast <byte, char>();
                retVal &= textEncoder.TryEncode(inputUtf16, encodedBytes, out charactersConsumed, out bytesWritten);
                retVal &= inputUtf16.Length == charactersConsumed;
                break;

            case SupportedEncoding.FromString:
                inputStringUtf16 = testEncoderUnicode.GetBytes(inputString);
                expectedBytes    = Text.Encoding.Convert(testEncoderUnicode, testEncoder, inputStringUtf16);
                encodedBytes     = new Span <byte>(new byte[expectedBytes.Length]);
                string inputStr = inputString;
                retVal &= textEncoder.TryEncode(inputStr, encodedBytes, /*out charactersConsumed,*/ out bytesWritten);
                //retVal &= inputString.Length == charactersConsumed;
                break;

            case SupportedEncoding.FromUtf32:
            default:
                byte[] inputStringUtf32 = testEncoderUtf32.GetBytes(inputString);
                expectedBytes = Text.Encoding.Convert(testEncoderUtf32, testEncoder, inputStringUtf32);
                encodedBytes  = new Span <byte>(new byte[expectedBytes.Length]);
                ReadOnlySpan <uint> input = inputStringUtf32.AsSpan().NonPortableCast <byte, uint>();
                retVal &= textEncoder.TryEncode(input, encodedBytes, out charactersConsumed, out bytesWritten);
                retVal &= input.Length == charactersConsumed;
                break;
            }

            retVal &= expectedBytes.Length == bytesWritten;
            retVal &= expectedBytes.AsSpan().SequenceEqual(encodedBytes);

            return(retVal);
        }
Exemple #13
0
 /// <summary>
 ///  Converts a string into a byte buffer including a zero terminator (needed for proper ETW message formatting)
 /// </summary>
 /// <param name="stringData">String to be converted to bytes</param>
 internal static byte[] StringToBytesZeroTerminated(string stringData)
 {
     Text.Encoding encoding = Text.Encoding.Unicode;
     int stringByteLength = encoding.GetByteCount(stringData);
     byte[] data = new byte[stringByteLength + sizeof(char)]; /* string + null termination */
     encoding.GetBytes(stringData, 0, stringData.Length, data, 0); // null terminator is already there, just write string over it
     return data;
 }
Exemple #14
0
        public void EncodeAllUnicodeCodePoints(bool useUtf8Encoder)
        {
            Text.Encoding systemEncoder         = useUtf8Encoder ? Text.Encoding.UTF8 : Text.Encoding.Unicode;
            const uint    maximumValidCodePoint = 0x10FFFF;

            uint[] codePoints = new uint[maximumValidCodePoint + 1];

            var plainText = new StringBuilder();

            for (int i = 0; i <= maximumValidCodePoint; i++)
            {
                if (!EncodingHelper.IsValidScalarValue((uint)i))
                {
                    codePoints[i] = 0; // skip unsupported characters
                    plainText.Append((char)0);
                }
                else
                {
                    codePoints[i] = (uint)i;

                    if (i > 0xFFFF)
                    {
                        plainText.Append(char.ConvertFromUtf32(i));
                    }
                    else
                    {
                        plainText.Append((char)i);
                    }
                }
            }

            ReadOnlySpan <uint> allCodePoints = codePoints;
            Span <byte>         buffer        = new byte[4 * (maximumValidCodePoint + 1)];
            int written;
            int consumed;

            if (useUtf8Encoder)
            {
                Assert.Equal(Buffers.OperationStatus.Done, Encodings.Utf32.ToUtf8(allCodePoints.AsBytes(), buffer, out consumed, out written));
            }
            else
            {
                Assert.Equal(Buffers.OperationStatus.Done, Encodings.Utf32.ToUtf16(allCodePoints.AsBytes(), buffer, out consumed, out written));
            }

            buffer = buffer.Slice(0, written);

            string unicodeString           = plainText.ToString();
            ReadOnlySpan <char> characters = unicodeString.AsReadOnlySpan();
            int byteCount = systemEncoder.GetByteCount(unicodeString);

            byte[] expectedBytes = new byte[byteCount];

            systemEncoder.GetBytes(characters.ToArray(), 0, characters.Length, expectedBytes, 0);

            Assert.Equal(expectedBytes.Length, buffer.Length);
            Assert.True(buffer.SequenceEqual(expectedBytes), "Bad output from system encoding comparison");
        }
Exemple #15
0
 /// <summary>
 ///   Reads the next value as character string with the specified tag and
 ///   encoding type, copying the decoded value into a provided destination buffer.
 /// </summary>
 /// <param name="expectedTag">The tag to check for before reading.</param>
 /// <param name="encodingType">
 ///   A <see cref="UniversalTagNumber"/> corresponding to the value type to process.
 /// </param>
 /// <param name="destination">The buffer in which to write.</param>
 /// <param name="charsWritten">
 ///   On success, receives the number of chars written to <paramref name="destination"/>.
 /// </param>
 /// <returns>
 ///   <c>true</c> and advances the reader if <paramref name="destination"/> had sufficient
 ///   length to receive the value, otherwise
 ///   <c>false</c> and the reader does not advance.
 /// </returns>
 /// <exception cref="ArgumentOutOfRangeException">
 ///   <paramref name="encodingType"/> is not a known character string type.
 /// </exception>
 /// <exception cref="CryptographicException">
 ///   the next value does not have the correct tag --OR--
 ///   the length encoding is not valid under the current encoding rules --OR--
 ///   the contents are not valid under the current encoding rules --OR--
 ///   the string did not successfully decode
 /// </exception>
 /// <exception cref="ArgumentException">
 ///   <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagClass"/> is
 ///   <see cref="TagClass.Universal"/>, but
 ///   <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagValue"/> is not the same as
 ///   <paramref name="encodingType"/>.
 /// </exception>
 /// <seealso cref="TryReadPrimitiveCharacterStringBytes(Asn1Tag,UniversalTagNumber,out ReadOnlyMemory{byte})"/>
 /// <seealso cref="TryCopyCharacterStringBytes(Asn1Tag,UniversalTagNumber,Span{byte},out int)"/>
 /// <seealso cref="ReadCharacterString(Asn1Tag,UniversalTagNumber)"/>
 public bool TryCopyCharacterString(
     Asn1Tag expectedTag,
     UniversalTagNumber encodingType,
     Span <char> destination,
     out int charsWritten)
 {
     Text.Encoding encoding = AsnCharacterStringEncodings.GetEncoding(encodingType);
     return(TryCopyCharacterString(expectedTag, encodingType, encoding, destination, out charsWritten));
 }
Exemple #16
0
        // T-REC-X.690-201508 sec 8.23
        private void WriteCharacterStringCore(Asn1Tag tag, Text.Encoding encoding, ReadOnlySpan <char> str)
        {
            int size = -1;

            // T-REC-X.690-201508 sec 9.2
            if (RuleSet == AsnEncodingRules.CER)
            {
                // TODO: Split this for netstandard vs netcoreapp for span?.
                unsafe
                {
                    fixed(char *strPtr = &MemoryMarshal.GetReference(str))
                    {
                        size = encoding.GetByteCount(strPtr, str.Length);

                        // If it exceeds the primitive segment size, use the constructed encoding.
                        if (size > AsnReader.MaxCERSegmentSize)
                        {
                            WriteConstructedCerCharacterString(tag, encoding, str, size);
                            return;
                        }
                    }
                }
            }

            // TODO: Split this for netstandard vs netcoreapp for span?.
            unsafe
            {
                fixed(char *strPtr = &MemoryMarshal.GetReference(str))
                {
                    if (size < 0)
                    {
                        size = encoding.GetByteCount(strPtr, str.Length);
                    }

                    // Clear the constructed tag, if present.
                    WriteTag(tag.AsPrimitive());
                    WriteLength(size);
                    Span <byte> dest = _buffer.AsSpan(_offset, size);

                    fixed(byte *destPtr = &MemoryMarshal.GetReference(dest))
                    {
                        int written = encoding.GetBytes(strPtr, str.Length, destPtr, dest.Length);

                        if (written != size)
                        {
                            Debug.Fail($"Encoding produced different answer for GetByteCount ({size}) and GetBytes ({written})");
                            throw new InvalidOperationException();
                        }
                    }

                    _offset += size;
                }
            }
        }
Exemple #17
0
        private string ReadCharacterString(
            Asn1Tag expectedTag,
            UniversalTagNumber universalTagNumber,
            Text.Encoding encoding)
        {
            byte[] rented = null;

            // T-REC-X.690-201508 sec 8.23.3, all character strings are encoded as octet strings.
            ReadOnlySpan <byte> contents = GetOctetStringContents(
                expectedTag,
                universalTagNumber,
                out int bytesRead,
                ref rented);

            try
            {
                string str;

                if (contents.Length == 0)
                {
                    str = string.Empty;
                }
                else
                {
                    unsafe
                    {
                        fixed(byte *bytePtr = &MemoryMarshal.GetReference(contents))
                        {
                            try
                            {
                                str = encoding.GetString(bytePtr, contents.Length);
                            }
                            catch (DecoderFallbackException e)
                            {
                                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
                            }
                        }
                    }
                }

                _data = _data.Slice(bytesRead);
                return(str);
            }
            finally
            {
                if (rented != null)
                {
                    Array.Clear(rented, 0, contents.Length);
                    ArrayPool <byte> .Shared.Return(rented);
                }
            }
        }
        private static string ReadCharacterStringCore(
            ReadOnlySpan <byte> source,
            AsnEncodingRules ruleSet,
            Asn1Tag expectedTag,
            UniversalTagNumber universalTagNumber,
            Text.Encoding encoding,
            out int bytesConsumed)
        {
            byte[]? rented = null;

            // T-REC-X.690-201508 sec 8.23.3, all character strings are encoded as octet strings.
            ReadOnlySpan <byte> contents = GetOctetStringContents(
                source,
                ruleSet,
                expectedTag,
                universalTagNumber,
                out int bytesRead,
                ref rented);

            string str;

            if (contents.Length == 0)
            {
                str = string.Empty;
            }
            else
            {
                unsafe
                {
                    fixed(byte *bytePtr = &MemoryMarshal.GetReference(contents))
                    {
                        try
                        {
                            str = encoding.GetString(bytePtr, contents.Length);
                        }
                        catch (DecoderFallbackException e)
                        {
                            throw new AsnContentException(SR.ContentException_DefaultMessage, e);
                        }
                    }
                }
            }

            if (rented != null)
            {
                CryptoPool.Return(rented, contents.Length);
            }

            bytesConsumed = bytesRead;
            return(str);
        }
        /// <summary>
        ///   Reads the next value as character string with the specified tag and
        ///   encoding type, returning the decoded string.
        /// </summary>
        /// <param name="source">The buffer containing encoded data.</param>
        /// <param name="ruleSet">The encoding constraints to use when interpreting the data.</param>
        /// <param name="encodingType">
        ///   One of the enumeration values which represents the value type to process.
        /// </param>
        /// <param name="bytesConsumed">
        ///   When this method returns, the total number of bytes for the encoded value.
        ///   This parameter is treated as uninitialized.
        /// </param>
        /// <param name="expectedTag">
        ///   The tag to check for before reading, or <see langword="null"/> for the universal tag that is
        ///   appropriate to the requested encoding type.
        /// </param>
        /// <returns>
        ///   The decoded value.
        /// </returns>
        /// <exception cref="ArgumentOutOfRangeException">
        ///   <paramref name="ruleSet"/> is not defined.
        ///
        ///   -or-
        ///
        ///   <paramref name="encodingType"/> is not a known character string type.
        /// </exception>
        /// <exception cref="AsnContentException">
        ///   the next value does not have the correct tag.
        ///
        ///   -or-
        ///
        ///   the length encoding is not valid under the current encoding rules.
        ///
        ///   -or-
        ///
        ///   the contents are not valid under the current encoding rules.
        ///
        ///   -or-
        ///
        ///   the string did not successfully decode.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///   <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagClass"/> is
        ///   <see cref="TagClass.Universal"/>, but
        ///   <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagValue"/> is not the same as
        ///   <paramref name="encodingType"/>.
        /// </exception>
        /// <seealso cref="TryReadPrimitiveCharacterStringBytes"/>
        /// <seealso cref="TryReadCharacterStringBytes"/>
        /// <seealso cref="TryReadCharacterString"/>
        public static string ReadCharacterString(
            ReadOnlySpan <byte> source,
            AsnEncodingRules ruleSet,
            UniversalTagNumber encodingType,
            out int bytesConsumed,
            Asn1Tag?expectedTag = null)
        {
            Text.Encoding encoding = AsnCharacterStringEncodings.GetEncoding(encodingType);

            return(ReadCharacterStringCore(
                       source,
                       ruleSet,
                       expectedTag ?? new Asn1Tag(encodingType),
                       encodingType,
                       encoding,
                       out bytesConsumed));
        }
        private void WriteConstructedCerCharacterString(Asn1Tag tag, Text.Encoding encoding, ReadOnlySpan <char> str, int size)
        {
            Debug.Assert(size > AsnReader.MaxCERSegmentSize);

            byte[] tmp     = CryptoPool.Rent(size);
            int    written = encoding.GetBytes(str, tmp);

            if (written != size)
            {
                Debug.Fail(
                    $"Encoding produced different answer for GetByteCount ({size}) and GetBytes ({written})");
                throw new InvalidOperationException();
            }

            WriteConstructedCerOctetString(tag, tmp.AsSpan(0, size));
            CryptoPool.Return(tmp, size);
        }
        private static bool TryReadCharacterStringCore(
            ReadOnlySpan <byte> source,
            AsnEncodingRules ruleSet,
            Asn1Tag expectedTag,
            UniversalTagNumber universalTagNumber,
            Text.Encoding encoding,
            Span <char> destination,
            out int bytesConsumed,
            out int charsWritten)
        {
            byte[]? rented = null;

            // T-REC-X.690-201508 sec 8.23.3, all character strings are encoded as octet strings.
            ReadOnlySpan <byte> contents = GetOctetStringContents(
                source,
                ruleSet,
                expectedTag,
                universalTagNumber,
                out int bytesRead,
                ref rented);

            bool copied = TryReadCharacterStringCore(
                contents,
                destination,
                encoding,
                out charsWritten);

            if (rented != null)
            {
                CryptoPool.Return(rented, contents.Length);
            }

            if (copied)
            {
                bytesConsumed = bytesRead;
            }
            else
            {
                bytesConsumed = 0;
            }

            return(copied);
        }
        /// <summary>
        ///   Reads a character string value from <paramref name="source"/> with a specified tag under
        ///   the specified encoding rules, copying the decoded string into a a provided destination buffer.
        /// </summary>
        /// <param name="source">The buffer containing encoded data.</param>
        /// <param name="destination">The buffer in which to write.</param>
        /// <param name="ruleSet">The encoding constraints to use when interpreting the data.</param>
        /// <param name="encodingType">
        ///   One of the enumeration values which represents the value type to process.
        /// </param>
        /// <param name="bytesConsumed">
        ///   When this method returns, the total number of bytes for the encoded value.
        ///   This parameter is treated as uninitialized.
        /// </param>
        /// <param name="charsWritten">
        ///   When this method returns, the number of chars written to <paramref name="destination"/>.
        ///   This parameter is treated as uninitialized.
        /// </param>
        /// <param name="expectedTag">
        ///   The tag to check for before reading, or <see langword="null"/> for the universal tag that is
        ///   appropriate to the requested encoding type.
        /// </param>
        /// <returns>
        ///   <see langword="true"/> and advances the reader if <paramref name="destination"/> had sufficient
        ///   length to receive the value, otherwise
        ///   <see langword="false"/> and the reader does not advance.
        /// </returns>
        /// <exception cref="ArgumentOutOfRangeException">
        ///   <paramref name="ruleSet"/> is not defined.
        ///
        ///   -or-
        ///
        ///   <paramref name="encodingType"/> is not a known character string type.
        /// </exception>
        /// <exception cref="AsnContentException">
        ///   the next value does not have the correct tag.
        ///
        ///   -or-
        ///
        ///   the length encoding is not valid under the current encoding rules.
        ///
        ///   -or-
        ///
        ///   the contents are not valid under the current encoding rules.
        ///
        ///   -or-
        ///
        ///   the string did not successfully decode.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///   <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagClass"/> is
        ///   <see cref="TagClass.Universal"/>, but
        ///   <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagValue"/> is not the same as
        ///   <paramref name="encodingType"/>.
        /// </exception>
        /// <seealso cref="TryReadPrimitiveCharacterStringBytes"/>
        /// <seealso cref="ReadCharacterString"/>
        public static bool TryReadCharacterString(
            ReadOnlySpan <byte> source,
            Span <char> destination,
            AsnEncodingRules ruleSet,
            UniversalTagNumber encodingType,
            out int bytesConsumed,
            out int charsWritten,
            Asn1Tag?expectedTag = null)
        {
            Text.Encoding encoding = AsnCharacterStringEncodings.GetEncoding(encodingType);

            return(TryReadCharacterStringCore(
                       source,
                       ruleSet,
                       expectedTag ?? new Asn1Tag(encodingType),
                       encodingType,
                       encoding,
                       destination,
                       out bytesConsumed,
                       out charsWritten));
        }
Exemple #23
0
        private bool TryCopyCharacterString(
            Asn1Tag expectedTag,
            UniversalTagNumber universalTagNumber,
            Text.Encoding encoding,
            Span <char> destination,
            out int charsWritten)
        {
            byte[] rented = null;

            // T-REC-X.690-201508 sec 8.23.3, all character strings are encoded as octet strings.
            ReadOnlySpan <byte> contents = GetOctetStringContents(
                expectedTag,
                universalTagNumber,
                out int bytesRead,
                ref rented);

            try
            {
                bool copied = TryCopyCharacterString(
                    contents,
                    destination,
                    encoding,
                    out charsWritten);

                if (copied)
                {
                    _data = _data.Slice(bytesRead);
                }

                return(copied);
            }
            finally
            {
                if (rented != null)
                {
                    Array.Clear(rented, 0, contents.Length);
                    ArrayPool <byte> .Shared.Return(rented);
                }
            }
        }
Exemple #24
0
        private static unsafe bool TryCopyCharacterString(
            ReadOnlySpan <byte> source,
            Span <char> destination,
            Text.Encoding encoding,
            out int charsWritten)
        {
            if (source.Length == 0)
            {
                charsWritten = 0;
                return(true);
            }

            fixed(byte *bytePtr = &MemoryMarshal.GetReference(source))
            fixed(char *charPtr = &MemoryMarshal.GetReference(destination))
            {
                try
                {
                    int charCount = encoding.GetCharCount(bytePtr, source.Length);

                    if (charCount > destination.Length)
                    {
                        charsWritten = 0;
                        return(false);
                    }

                    charsWritten = encoding.GetChars(bytePtr, source.Length, charPtr, destination.Length);
                    Debug.Assert(charCount == charsWritten);
                }
                catch (DecoderFallbackException e)
                {
                    throw new CryptographicException(SR.Resource("Cryptography_Der_Invalid_Encoding"), e);
                }

                return(true);
            }
        }
        /// <summary>Initializes a new instance of <see cref="SecureOnPassword"/> with the given password.</summary>
        /// <param name="password">The password as <see cref="String"/>.</param>
        /// <param name="encoding">The <see cref="Text.Encoding"/> instance to use for the password.</param>
        /// <exception cref="ArgumentNullException"><paramref name="password"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="encoding"/> is null.</exception>
        /// <exception cref="ArgumentException">The <see cref="Byte"/> array wich is created using the password has more elements than 6.</exception>
        public SecureOnPassword(string password, Text.Encoding encoding)
        {
            if (password == null)
            {
                throw new ArgumentNullException(nameof(password));
            }
            if (encoding == null)
            {
                throw new ArgumentNullException(nameof(encoding));
            }

            if (string.IsNullOrEmpty(password))
            {
                _password = new byte[6];
            }

            var bytes = encoding.GetBytes(password);

            if (bytes.Length > 6)
            {
                throw new ArgumentException(Localization.ArgumentExceptionInvalidPasswordLength);
            }

            _password = new byte[6];
            for (int i = 0; i < bytes.Length; i++)
            {
                _password[i] = bytes[i];
            }
            if (bytes.Length < 6)
            {
                for (int i = bytes.Length - 1; i < 6; i++)
                {
                    _password[i] = 0x00;
                }
            }
        }
        private static unsafe bool TryReadCharacterStringCore(
            ReadOnlySpan <byte> source,
            Span <char> destination,
            Text.Encoding encoding,
            out int charsWritten)
        {
            if (source.Length == 0)
            {
                charsWritten = 0;
                return(true);
            }

            fixed(byte *bytePtr = &MemoryMarshal.GetReference(source))
            fixed(char *charPtr = &MemoryMarshal.GetReference(destination))
            {
                try
                {
                    int charCount = encoding.GetCharCount(bytePtr, source.Length);

                    if (charCount > destination.Length)
                    {
                        charsWritten = 0;
                        return(false);
                    }

                    charsWritten = encoding.GetChars(bytePtr, source.Length, charPtr, destination.Length);
                    Debug.Assert(charCount == charsWritten);
                }
                catch (DecoderFallbackException e)
                {
                    throw new AsnContentException(SR.ContentException_DefaultMessage, e);
                }

                return(true);
            }
        }
Exemple #27
0
 /// <summary>
 ///   Reads the next value as character string with the specified tag and
 ///   encoding type, returning the decoded value as a <see cref="string"/>.
 /// </summary>
 /// <param name="expectedTag">The tag to check for before reading.</param>
 /// <param name="encodingType">
 ///   A <see cref="UniversalTagNumber"/> corresponding to the value type to process.
 /// </param>
 /// <returns>
 ///   the decoded value as a <see cref="string"/>.
 /// </returns>
 /// <exception cref="ArgumentOutOfRangeException">
 ///   <paramref name="encodingType"/> is not a known character string type.
 /// </exception>
 /// <exception cref="CryptographicException">
 ///   the next value does not have the correct tag --OR--
 ///   the length encoding is not valid under the current encoding rules --OR--
 ///   the contents are not valid under the current encoding rules --OR--
 ///   the string did not successfully decode
 /// </exception>
 /// <exception cref="ArgumentException">
 ///   <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagClass"/> is
 ///   <see cref="TagClass.Universal"/>, but
 ///   <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagValue"/> is not the same as
 ///   <paramref name="encodingType"/>.
 /// </exception>
 /// <seealso cref="TryReadPrimitiveCharacterStringBytes(Asn1Tag,UniversalTagNumber,out ReadOnlyMemory{byte})"/>
 /// <seealso cref="TryCopyCharacterStringBytes(Asn1Tag,UniversalTagNumber,Span{byte},out int)"/>
 /// <seealso cref="TryCopyCharacterString(Asn1Tag,UniversalTagNumber,Span{char},out int)"/>
 public string ReadCharacterString(Asn1Tag expectedTag, UniversalTagNumber encodingType)
 {
     Text.Encoding encoding = AsnCharacterStringEncodings.GetEncoding(encodingType);
     return(ReadCharacterString(expectedTag, encodingType, encoding));
 }
Exemple #28
0
 /// <summary>
 /// Asynchronous extension for <see cref="File.WriteAllText" /> method.
 /// </summary>
 /// <param name="path">Same with <see cref="File.WriteAllText" /> path.</param>
 /// <param name="contents">Same with <see cref="File.WriteAllText" /> contents.</param>
 /// <param name="encoding">Same with <see cref="File.WriteAllText" /> encoding.</param>
 /// <param name="cancellationToken">A <see cref="CancellationToken" /> that should be used to cancel the work.</param>
 /// <returns>A <see cref="Task"/> that represents the work queued to execute in the ThreadPool.</returns>
 public static async Task WriteAllTextAsync(string path, string contents, Text.Encoding encoding, CancellationToken cancellationToken = default(CancellationToken))
 {
     await Task.Run(() => File.WriteAllText(path, contents, encoding), cancellationToken);
 }
Exemple #29
0
 /// <summary>
 /// Asynchronous extension for <see cref="File.ReadAllText" /> method.
 /// </summary>
 /// <param name="path">Same with <see cref="File.ReadAllText" /> path.</param>
 /// <param name="encoding">Same with <see cref="File.ReadAllText" /> encoding.</param>
 /// <param name="cancellationToken">A <see cref="CancellationToken" /> that should be used to cancel the work.</param>
 /// <returns>A <see cref="Task"/> that represents the work queued to execute in the ThreadPool.</returns>
 public static async Task <string> ReadAllTextAsync(string path, Text.Encoding encoding, CancellationToken cancellationToken = default(CancellationToken))
 {
     return(await Task.Run(() => File.ReadAllText(path, encoding), cancellationToken));
 }
Exemple #30
0
        /// <summary>
        ///   Write the provided string using the specified encoding type using the UNIVERSAL
        ///   tag corresponding to the encoding type.
        /// </summary>
        /// <param name="encodingType">
        ///   The <see cref="UniversalTagNumber"/> corresponding to the encoding to use.
        /// </param>
        /// <param name="str">The string to write.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///   <paramref name="encodingType"/> is not a restricted character string encoding type --OR--
        ///   <paramref name="encodingType"/> is a restricted character string encoding type that is not
        ///   currently supported by this method
        /// </exception>
        /// <exception cref="ObjectDisposedException">The writer has been Disposed.</exception>
        /// <seealso cref="WriteCharacterString(Asn1Tag,UniversalTagNumber,ReadOnlySpan{char})"/>
        public void WriteCharacterString(UniversalTagNumber encodingType, ReadOnlySpan <char> str)
        {
            Text.Encoding encoding = AsnCharacterStringEncodings.GetEncoding(encodingType);

            WriteCharacterStringCore(new Asn1Tag(encodingType), encoding, str);
        }