dotnet / docs

This repository contains .NET Documentation.
https://learn.microsoft.com/dotnet
Creative Commons Attribution 4.0 International
4.28k stars 5.91k forks source link

[Breaking change]: X500DistinguishedName more strictly validates inputs on non-Windows systems #43284

Open vcsjones opened 2 weeks ago

vcsjones commented 2 weeks ago

Description

When using new X500DistinguishedName that accepts a string-encoded distinguished name, the distinguished name may be rejected as invalid input where it was previously allowed, or may be encoded differently on non-Windows systems. This more closely aligns with encoding specifications and with Windows.

Version

.NET 10 Preview 1

Previous behavior

Previous versions of .NET on non-Windows systems would permit incorrect distinguished names, or encode them in a way that is not permitted by X.520 encoding rules.

Additionally, the X500DistinguishedNameFlags.ForceUTF8Encoding flag would permit forcing components to use a UTF8String in the encoded ASN.1 even if UTF8String is not a valid representation of that component.

New behavior

Starting in .NET 10, components that violate their encoding rules will throw a CryptographicException on non-Windows systems to match the behavior when run on Windows.

Starting in .NET 10, the X500DistinguishedNameFlags.ForceUTF8Encoding flag will only UTF-8 encode components when it is permissible to do so.

Type of breaking change

Reason for change

Different X.500 components have differing rules for encoding their representation. For example, the id-at-telephoneNumber component is encoded as an ASN.1 PrintableString, and this is the only permitted encoding of that component.

The exclamation point character is not a valid character for a PrintableString, so consider:

new X500DistinguishedName("Phone=!!");

On Windows, this would throw an exception. Non-Windows platforms, however, would encode this as a UTF8String.

Similarly, if X500DistinguishedNameFlags.ForceUTF8Encoding was used with a telephone number that is valid, it would force the encoding to UTF8String even though it was not permitted to do so.

For example

new X500DistinguishedName("Phone=000-555-1234", X500DistinguishedNameFlags.ForceUTF8Encoding);

On non-Windows, this would previously encode the phone number as a UTF8String. After this change, the phone number remains encoded as a PrintableString because that is the only valid encoding of a telephone number.

These changes bring encoding of all distinguished name components closer to their intended representation by the specification, as well as closer in behavior to Windows.

Recommended action

Generally, no action is needed unless you need to maintain compatibility with the incorrect encoding.

If you need to continue to create X.500 names and force a particular encoding for components, the X500DistinguishedNameBuilder can be used to create X500DistinguishedName instances with the desired encoding.

For example:

using System.Formats.Asn1;
using System.Security.Cryptography.X509Certificates;

X500DistinguishedNameBuilder builder = new();

// Compatibility: Create a telephone number as a UTF8String
builder.Add("2.5.4.20", "000-555-1234", UniversalTagNumber.UTF8String);
X500DistinguishedName dn = builder.Build();

Feature area

Cryptography

Affected APIs

vcsjones commented 2 weeks ago

/cc @bartonjs

bartonjs commented 2 weeks ago

I made some minor tweaks, mostly around the !! example.