Кодировка JavaScript иногда дает другой вывод, чем кодировка C# - PullRequest
0 голосов
/ 19 марта 2020

Мы хотим войти в систему QNAP NAS через API, и поэтому пароль должен быть закодирован. В документации указано, что этот скрипт используется для кодирования: http://eu1.qnap.com/Storage/SDK/get_sid.js

Это похоже на кодировку base64, и я хочу иметь возможность кодировать пароли в C#, так как мы будем вызывать API из написанного C# бэкэнда. Поэтому я попытался проверить кодировку с помощью следующего 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» выдает «YWRtaW4xMjM0» как для кода JavaScript, так и для кода C#, а также наш реальный пароль кодируется в одно и то же значение для кода 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;
    }

Но результат тот же. Мой вопрос: что вызывает разницу в выводе при использовании специальных символов?

...