Convert.FromBase64String有时返回unicode,或UTF-8

dav*_*ner 5 c# unicode base64 encoding utf-8

有时字节数组b64是UTF-8,其他时间是UTF-16.我一直在网上看到C#字符串总是UTF-16,但这不是我的情况.为什么会发生这种情况,我该如何解决?我有一个简单的方法将base64字符串转换为普通字符串:

public static string FromBase64(this string input)
{
    String corrected = new string(input.ToCharArray());
    byte[] b64 = Convert.FromBase64String(corrected);
    if (b64[1] == 0)
    {
        return System.Text.Encoding.Unicode.GetString(b64);
    }
    else
    {
        return System.Text.Encoding.UTF8.GetString(b64);
    }

}
Run Code Online (Sandbox Code Playgroud)

我的base 64编码器也发生了同样的事情:

public static string ToBase64(this string input)
{
    String b64 = Convert.ToBase64String(input.GetBytes());
    return b64;
}

public static byte[] GetBytes(this string str)
{
    byte[] bytes = new byte[str.Length * sizeof(char)];
    System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
    return bytes;
}
Run Code Online (Sandbox Code Playgroud)

示例:在我的计算机上,"cABhAHMAcwB3AG8AcgBkADEA"解码为:

'p','\0','a','\0','s','\0','s','\0','w','\0','o','\0','r','\0','d','\0','1','\0'
Run Code Online (Sandbox Code Playgroud)

但在我的同事计算机上它是:

'p','a','s','s','w','o','r','d','1'
Run Code Online (Sandbox Code Playgroud)

编辑:

我知道我创建的字符串来自一个文本框,我保存到的文件总是为UTF-8,所以一切都指向导致我的编码开关的Convert方法.

更新:

在进一步深入挖掘之后,我的同事看起来在他的代码版本中有一条非常重要的一行,该代码将从文件中读取的值保存到哈希表中.我使用的默认值是UTF-8 base64值,所以我要将默认值更正为utf-16值,然后我可以清除删除任何UTF8引用的代码.

此外,我一直天真地使用我从网站上检索到的UTF-8 base64编码,没有意识到我自己进入了什么.有趣的是,如果我的同事没有评论保存文件中值的行,我就永远不会发现这个事实.

代码的最终版本:

public static string FromBase64(this string input)
{
    byte[] b64 = Convert.FromBase64String(input);
    return System.Text.Encoding.Unicode.GetString(b64);
}

public static string ToBase64(this string input)
{
    String b64 = Convert.ToBase64String(input.GetBytes());
    return b64;
}

public static byte[] GetBytes(this string str)
{
    return System.Text.Encoding.Unicode.GetBytes(str);
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 9

首先,我想揭穿问题的标题:

Convert.FromBase64String() 有时返回Unicode,或UTF-8

事实并非如此.然后给出相同的输入,有效的base64编码文本,Convert.FromBase64String()总是返回相同的输出.

继续前进,只能通过检查有效负载(用于字符串的编码)来确定无法确定.你试图这样做

if (b64[1] == 0)
    // encoding must be UTF-16
Run Code Online (Sandbox Code Playgroud)

不是这种情况.绝大多数UTF-16字符元素都无法通过该测试.如果你试图写这个测试并不重要,它注定要失败.这是因为存在字节数组,当被解释为不同的编码时,它们是定义良好的字符串.换句话说,例如,可以构造在被视为UTF-8或UTF-16时有效的字节数组.

因此,您必须先了解有效载荷是否编码为UTF-16,UTF-8或其他编码.

解决方案是在base64编码之前跟踪原始编码.将该信息与base64编码的有效负载一起传递.然后在解码时,您可以确定Encoding使用哪个解码回字符串.

在我看来,你的字符串都来自UTF-16 .net字符串.在这种情况下,您将永远不会有UTF-8字符串,并且应始终解码UTF-16.那是你用的Encoding.Unicode.GetString().

此外,GetBytes您的代码中的方法很差.它应该是:

public static byte[] GetBytes(this string str)
{
    return Encoding.Unicode.GetBytes(str);
}
Run Code Online (Sandbox Code Playgroud)

另一个奇怪之处:

String corrected = new string(input.ToCharArray());
Run Code Online (Sandbox Code Playgroud)

这是一个无操作.

最后,当编码为UTF-8时,您的文本很可能会更紧凑.因此,在应用base64编码之前,您应该考虑这样做.


关于您的更新,您声明的内容不正确.这段代码:

string str = Encoding.Unicode.GetString(
    Convert.FromBase64String("cABhAHMAcwB3AG8AcgBkADEA"));
Run Code Online (Sandbox Code Playgroud)

分配password1到str它运行的任何地方.