我们想通过 API 登录 QNAP NAS,因此需要对密码进行编码。在文档中声明使用此脚本进行编码:http ://eu1.qnap.com/Storage/SDK/get_sid.js
这似乎是一种 base64 编码,我希望能够在 C# 中对密码进行编码,因为我们将从 C# 编写的后端调用 API。所以我尝试使用以下 C# 代码测试编码:
public static class EncodeHelper
{
private const string EzEncodechars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
public static string Utf16to8(string input)
{
byte[] utf16Bytes = Encoding.Unicode.GetBytes(input);
byte[] utf8Bytes = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, utf16Bytes);
char[] chars = (char[])Array.CreateInstance(typeof(char), utf8Bytes.Length);
for (int i = 0; i < utf8Bytes.Length; i++)
{
chars[i] = BitConverter.ToChar(new byte[2] { utf8Bytes[i], 0 }, 0);
}
return new string(chars);
}
public static string Encode(string input)
{
var utf8Input = Utf16to8(input);
var plainTextBytes = Encoding.UTF8.GetBytes(utf8Input);
return Convert.ToBase64String(plainTextBytes);
}
}
大多数测试用例给出相同的输出。例如:“admin1234”将 JavaScript 代码作为 C# 代码给出“YWRtaW4xMjM0”,并且我们的真实密码对于 JavaScript 代码和 C# 代码都被编码为相同的值。但是当我尝试编码这个字符串时:“äçéè”,输出不同。JavaScript 返回“w6TDp8Opw6g=”,但 C# 返回“w4PCpMODwqfDg8Kpw4PCqA==”。
似乎 utf16to8 函数不是导致不同输出的原因:JavaScript 和 C# 都将“äçéè”转换为“äçéè”,因此在 ToBase64String 或 GetBytes 方法中似乎发生了一些不同的事情。我也尝试像这样手动编码:
public static string Encode(string input)
{
//var utf8Input = Utf16to8(input);
//var plainTextBytes = Encoding.UTF8.GetBytes(utf8Input);
//return Convert.ToBase64String(plainTextBytes);
var index = 0;
var inputLength = input.Length;
var output = "";
while (index < inputLength)
{
var char1 = input[index++] & 0xff;
if (index == inputLength)
{
output += EzEncodechars[char1 >> 2];
output += EzEncodechars[(char1 & 0x3) << 4];
output += "==";
break;
}
var char2 = input[index++];
if (index == inputLength)
{
output += EzEncodechars[char1 >> 2];
output += EzEncodechars[((char1 & 0x3) << 4) | ((char2 & 0xF0) >> 4)];
output += EzEncodechars[(char2 & 0xF) << 2];
output += "=";
break;
}
var char3 = input[index++];
output += EzEncodechars[char1 >> 2];
output += EzEncodechars[((char1 & 0x3) << 4) | ((char2 & 0xF0) >> 4)];
output += EzEncodechars[((char2 & 0xF) << 2) | ((char3 & 0xC0) >> 6)];
output += EzEncodechars[char3 & 0x3F];
}
return output;
}
但结果是一样的。我的问题是:使用特殊字符时导致输出差异的原因是什么?