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]); } }
/// <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); }
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; }
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); }
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); }
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(); } } } }
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(); } } } }
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); }
/// <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; }
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"); }
/// <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)); }
// 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; } } }
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)); }
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); } } }
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); } }
/// <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)); }
/// <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); }
/// <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)); }
/// <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); }