3

Fix Encoding.Default.GetChars() Result Different in .NET Framework and .NET 6

 1 year ago
source link: https://edi.wang/post/2022/9/2/encoding-default-diff-netfx-net6
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Fix Encoding.Default.GetChars() Result Different in .NET Framework and .NET 6

Original

Edi Wang

Friday, September 2, 2022 China Standard Time

17 Reads


Problem


I am upgrading a 16 year old legacy application from .NET Framework to .NET 6 these days. There is a custom encryption method that uses Encoding.Default.GetChars() method, which output wrong result in .NET 6. 

// .NET 6.0 output: �
// .NET Framework output: „
Encoding.Default.GetChars(new byte[] { 132 });

It is well known that using Encoding.Default is a very bad practice, but it is after all a 16 years old application, this piece of encryption method is still running at the very fundamental core of our banking system. I have to keep the output same as before. Let's see how to fix this.

Root Cause


After work 996, I found Encoding.Default is using UTF8 (65001), it is consistent on every machine with .NET 6. 

img-1ddc0e7c-3e87-4a59-9a23-23a5730a7fc7.png

However, .NET Framework which runs only on Windows, is using the system encoding for Encoding.Default

On a English (US) version of Windows, it uses SBCSCodePageEncoding (BodyName iso-8859-1, CodePage 1252). But a Chinese version of Windows or English version of Windows with Chinese set as non-Unicode programs. It will use GB2312 (936), which will output another result.

img-a1c4e58c-5884-45f1-aa7f-6496f7242a4d.png
img-1a071b9e-96b3-4955-85f2-a0bd80c9f6fa.png

Our datacenters happen to be using only English version of Windows Server for decades, and we don't change system locale. So this potential bug that can blow our banking system sky high never happens before. Pure luck!


In both .NET 6 and .NET Framework, we can explicitly set encoding by Encoding.GetEncoding() method. In my case, the change code to.

Encoding.GetEncoding(1252).GetChars(new byte[] { 132 })

There is still one thing to notice. In .NET 6.0, code page 1252 is not included by default, so you will need to register encoding providers first.

Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

Now we can get same output on every system regardless of their system level locale!

img-f80c8019-6519-4256-b023-f7eae2c4e3a3.png

This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License



About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK