Assert.Equal(expected, actual);
}
+ [Fact]
+ public static void ForceUtf8EncodingWithFlagWhenEncoding()
+ {
+ // Even though these values are encodable as a PrintableString, the flag should force them to be encoded
+ // as UTF8String.
+ X500DistinguishedName name = new X500DistinguishedName(
+ "CN=potato, O=jicama",
+ X500DistinguishedNameFlags.ForceUTF8Encoding);
+
+ ReadOnlySpan<byte> expectedDer = new byte[]
+ {
+ 0x30, 0x22,
+ 0x31, 0x0F,
+ 0x30, 0x0D,
+ 0x06, 0x03, 0x55, 0x04, 0x03, // id-at-commonName OID
+ 0x0C, 0x06, 0x70, 0x6F, 0x74, 0x61, 0x74, 0x6F, // 0x0C is UTF8String
+ 0x31, 0x0F,
+ 0x30, 0x0D,
+ 0x06, 0x03, 0x55, 0x04, 0x0A, // id-at-organizatioName OID
+ 0x0C, 0x06, 0x6A, 0x69, 0x63, 0x61, 0x6D, 0x61, // 0x0C is UTF8String
+ };
+
+ AssertExtensions.SequenceEqual(expectedDer, name.RawData);
+ }
+
[Theory]
[InlineData(false)]
[InlineData(true)]
{
bool reverse = (flags & X500DistinguishedNameFlags.Reversed) == X500DistinguishedNameFlags.Reversed;
bool noQuotes = (flags & X500DistinguishedNameFlags.DoNotUseQuotes) == X500DistinguishedNameFlags.DoNotUseQuotes;
+ bool forceUtf8Encoding = (flags & X500DistinguishedNameFlags.ForceUTF8Encoding) == X500DistinguishedNameFlags.ForceUTF8Encoding;
List<char> dnSeparators;
Debug.Assert(dnSeparators.Count != 0);
- List<byte[]> encodedSets = ParseDistinguishedName(stringForm, dnSeparators, noQuotes);
+ List<byte[]> encodedSets = ParseDistinguishedName(stringForm, dnSeparators, noQuotes, forceUtf8Encoding);
if (reverse)
{
private static List<byte[]> ParseDistinguishedName(
string stringForm,
List<char> dnSeparators,
- bool noQuotes)
+ bool noQuotes,
+ bool forceUtf8Encoding)
{
// 16 is way more RDNs than we should ever need. A fairly standard set of values is
// { E, CN, O, OU, L, S, C } = 7;
Debug.Assert(valueEnd != -1);
Debug.Assert(valueStart != -1);
- encodedSets.Add(ParseRdn(tagOid, chars[valueStart..valueEnd], hadEscapedQuote));
+ encodedSets.Add(ParseRdn(tagOid, chars[valueStart..valueEnd], hadEscapedQuote, forceUtf8Encoding));
hasTagOid = false;
valueStart = -1;
valueEnd = -1;
Debug.Assert(valueStart != -1);
Debug.Assert(valueEnd != -1);
- encodedSets.Add(ParseRdn(tagOid, chars[valueStart..valueEnd], hadEscapedQuote));
+ encodedSets.Add(ParseRdn(tagOid, chars[valueStart..valueEnd], hadEscapedQuote, forceUtf8Encoding));
break;
// If the entire string was empty, or ended in a dnSeparator.
return new Oid(str.ToString()).Value; // Value can be null, but permit the null-to-empty conversion.
}
- private static byte[] ParseRdn(ReadOnlySpan<char> tagOid, ReadOnlySpan<char> chars, bool hadEscapedQuote)
+ private static byte[] ParseRdn(ReadOnlySpan<char> tagOid, ReadOnlySpan<char> chars, bool hadEscapedQuote, bool forceUtf8Encoding)
{
scoped ReadOnlySpan<char> data;
throw new CryptographicException(SR.Cryptography_Invalid_IA5String);
}
}
+ else if (forceUtf8Encoding)
+ {
+ writer.WriteCharacterString(UniversalTagNumber.UTF8String, data);
+ }
else
{
try