Я получаю случайные символы Юникода в моем файле JSON, когда я его расшифровываю

я делаю шифрование AES для своего файла сохранения, но при расшифровке я получаю случайные символы Юникода в своем json-файле

{"s➴uls":1800.0} при расшифровке

{"souls":1800.0} (то, что я ожидал)

using System.IO;
using System.Security.Cryptography;
using System.Text;
using System;

public static class Save
{
    public static void SaveStats () 
    {
        PlayerData data = new PlayerData();

        string savedPlayerData = JsonUtility.ToJson(data);

        string encrypteddata = EncryptFratamus(savedPlayerData);

        string path = Application.persistentDataPath + "/DDGS1_data.json";

        FileStream stream = new FileStream(path, FileMode.Create);

        using (StreamWriter writer = new StreamWriter(stream)) 
        {
            writer.Write(encrypteddata);
        }
    }

    public static PlayerData LoadPlayer() 
    {
        string path = Application.persistentDataPath + "/DDGS1_data.json";

        if (File.Exists(path)) 
        {
            string savedPlayerData;


            using (StreamReader reader = new StreamReader(path)) 
            {
                savedPlayerData = reader.ReadToEnd();
            }

            string decryptdata = DecryptFratamus(savedPlayerData);

            PlayerData data = JsonUtility.FromJson<PlayerData>(decryptdata);

            return data;
        } else 
        {
            Debug.Log("ERROR CODE #0 \n Savefile not found at" + path); 
            return null;
        }
    }

    static byte[] IVbytes = new byte[16];
    static byte[] KEYbytes = new byte[16];

    static void GenerateIVByets() 
    {
        System.Random rnd = new System.Random();
        rnd.NextBytes(IVbytes);

        Debug.Log(IVbytes);
    }

    static void GenerateKeys() 
    {
        int sum = 0;
        foreach (char charr in "i ain't giving you the key")
            sum += charr;

        System.Random rnd = new System.Random(sum);
        rnd.NextBytes(KEYbytes);
    }

    public static string EncryptFratamus(string data)
    {
        GenerateIVByets();
        GenerateKeys();

        SymmetricAlgorithm algorithm = Aes.Create();
        ICryptoTransform transform = algorithm.CreateEncryptor(KEYbytes, IVbytes);
        byte[] inputbuffer = Encoding.Unicode.GetBytes(data);
        byte[] outputbuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length);

        string IVstring = Encoding.Unicode.GetString(IVbytes);
        string encryptedstring = Convert.ToBase64String(outputbuffer);

        return IVstring + encryptedstring;
    }

    public static string DecryptFratamus(this string txt) 
    {
        GenerateIVByets();
        GenerateKeys();

        int endOfIvBytes = IVbytes.Length/2;

        string ivString = txt.Substring(0, endOfIvBytes);
        byte[] extractedBytes = Encoding.Unicode.GetBytes(ivString);

        string encryptedString = txt.Substring(endOfIvBytes);

        SymmetricAlgorithm alg = Aes.Create();

        ICryptoTransform trans = alg.CreateDecryptor(KEYbytes, extractedBytes);

        byte[] input = Convert.FromBase64String(encryptedString);
        byte[] output = trans.TransformFinalBlock(input, 0, input.Length);

        string decrypted = Encoding.Unicode.GetString(output);

        return decrypted;
    }
}

я пытался перейти от записи/чтения всего текста к средству записи потока, чтобы проверить, не произошла ли какая-то ошибка записи в процессе, но безуспешно

(да, я уже пробовал менять ключ)

Удаление rnd.NextBytes(IVbytes); из GenerateIVByets исправляет ситуацию. Я предполагаю, что что-то в том, что генерируемые байты, представленные в символах, не всегда имеют ожидаемую длину, из-за чего часть подстроки становится странной.

Xiang Wei Huang 23.09.2023 02:56

спасибо чувак, это исправили

Clans 2 23.09.2023 09:14

Если вы просто удалили его, то часть шифрования исчезла, и ваш файл сохранения теперь в основном имеет формат Base64. Его удаление предназначено просто для проверки того, в какой части возникла проблема, а не для решения!

Xiang Wei Huang 23.09.2023 10:29
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
3
72
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Причина, по которой при расшифровке вы получаете забавные символы, заключается в том, что IVstring поврежден.

  • Код принимает случайные байты IV и притворяется, что это допустимые байты Юникода. И не все байты действительны в Юникоде. Вам лучше сохранить байты IV как есть (или использовать base64, чтобы следовать вашему методу хранения зашифрованных байтов).

  • Когда вы перечитываете IVstring из файла, вы получаете другое значение только для некоторых символов. (Попробуйте вывести IVstring при шифровании и расшифровке, чтобы убедиться в этом сами.)

  • Я бы сохранил как IV, так и зашифрованный текст, используя одну и ту же кодировку. То есть либо храните все в двоичном виде (как есть), либо используйте base64 в обоих случаях. Если вы используете base64, вы можете разделить их точкой (.), как это делают токены JWT.

Однако ваш код имеет несколько проблем с точки зрения безопасности.

  • Прежде всего, никогда не используйте генератор псевдослучайных чисел System.Random при работе с шифрованием, всегда используйте RandomNumberGenerator от System.Security.Cryptography.

  • Удалите GenerateIVByets() из DecryptFratamus(), поскольку вы извлекаете IV из зашифрованного зашифрованного текста. (Это правильное поведение. Оно просто не работает для некоторых байтов в вашей реализации.)

  • Лично я бы предпочел вернуть IV и ключевые байты, а не устанавливать статический член класса. (Который можно прочитать в любом месте кода. Вместо этого используйте static byte[] GenerateIVByets().)

static byte[] GenerateKeys() ошибочен. Фактическая реализация будет зависеть от того, как вы храните секретный пароль/ключ, и от необходимого вам уровня безопасности.

  • Текущая реализация использует «пароль» "i ain't giving you the key" для заполнения генератора псевдослучайных чисел.

  • Вам лучше использовать правильную хеш-функцию для секретного ключа, чтобы получить массив байтов.

  • Если «важность» заключается только в шифровании файла сохранения, то быстрой хэш-функции, такой как SHA1, может быть достаточно.

  • Если вам нужна более высокая безопасность, вам лучше выбрать медленную хэш-функцию, такую ​​​​как bcrypt или Argon2, которые были созданы, чтобы противостоять атакам грубой силы.

  • Настоящая проблема заключается в том, как вы храните сам секретный ключ. Эта реализация хранит "i ain't giving you the key" в виде простой строки, которую можно легко прочитать из конечного файла .exe. (И здесь, опять же, это будет зависеть от необходимого вам уровня безопасности.)

  • Если вы ожидаете, что пользователь сможет ввести секретный пароль, вам следует нормализовать строку Unicode перед ее хешированием:

    string pw = "i ain't giving you the key";

    byte[] KEYbytes = SHA1.HashData(UnicodeEncoding.UTF8.GetBytes(pw.Normalize()));

  • Последняя проблема, которую я вижу, заключается в том, что зашифрованный файл «поддается обработке». Это означает, что вы можете немного перевернуть сохраненный зашифрованный файл, и расшифровка все равно будет работать. Вы используете Aes.Create(), который по умолчанию использует режим AES CBC. (С помощью CBC вы не сможете успешно перевернуть ни один байт, но в CBC по-прежнему нет встроенных средств защиты.)

  • Если вы используете AES-GCMAesGcm(), метод расшифровки определит, был ли зашифрованный файл изменен.

  • Если вы решите использовать AES-GCM, абсолютно важно, чтобы у вас каждый раз был НОВЫЙ случайный IV. (Пока секретный ключ остается прежним.) В противном случае метод GCM завершится неудачей. IV в этом случае обычно называется nonce (n-once, используется только один раз).

  • Решением этой проблемы является использование нового алгоритма AES-GCM-SIV, который вычисляет IV/nonce на основе текстовых данных. К сожалению, он пока не является частью стандартной библиотеки .Net. Еще одним недостатком этого алгоритма является то, что два идентичных текстовых объекта PlayerData будут зашифрованы в два идентичных зашифрованных файла. (Иногда это критический недостаток, иногда неважный, а иногда и преимущество. В зависимости от ситуации.)

Извините, длинный ответ.

Слишком долго; не читал Если вы просто хотите затруднить редактирование файла сохранения, просто сначала исправьте поврежденное IVstring упоминание. Вам будет хорошо.

Если вы хотите узнать больше о шифровании. Прочтите список и выберите, что вы хотели бы попробовать, и узнайте о нем больше.

Приятного кодирования! Наслаждайтесь обучением! :)

Я действительно не могу налюбоваться тобой, чувак, ты в одиночку научил меня шифрованию, кодированию и в то же время исправил проблемы с моим сценарием, абсолютная легенда.

Clans 2 25.09.2023 19:22

Другие вопросы по теме