Unity как шифровать данные в json
Перейти к содержимому

Unity как шифровать данные в json

  • автор:

Сериализация JSON

Используйте класс JsonUtility для преобразования объектов Unity в JSON формат. Например, сериализацию JSON можно использовать для взаимодействия с веб-службами или для простой упаковки и распаковки данных в текстовый формат.

Сериализация JSON использует понятие «структурированного» JSON: вы создаете класс или структуру для описания того, какие переменные вы хотите хранить в своих данных JSON. Например:

[Serializable] public class MyClass

Это определяет простой класс C#, содержащий три переменные (level, timeElapsed и playerName), и помечает его Serializable для работы с сериализатором JSON. Чтобы создать экземпляр вашего класса, вы можете использовать что-то вроде этого:

MyClass myObject = new MyClass(); myObject.level = 1; myObject.timeElapsed = 47.5f; myObject.playerName = «Dr Charles Francis»;

Затем используйте метод JsonUtility.ToJson, чтобы сериализовать его (преобразовать) в формат JSON:

Чтобы преобразовать JSON обратно в объект, используйте JsonUtility.FromJson:

myObject = JsonUtility.FromJson (json);

Это создает новый экземпляр MyClass и задает для него значения с использованием данных JSON. Если данные JSON содержат значения, не соответствующие полям в MyClass , сериализатор игнорирует эти значения. Если в данных JSON отсутствуют значения для полей в MyClass , сериализатор оставляет созданные значения для этих полей в возвращаемом объекте.

Перезапись объектов с помощью JSON

Вы также можете десериализовать данные JSON поверх существующего объекта, что перезапишет любые существующие данные:

Если данные JSON не содержат значения для поля, сериализатор не изменяет значение этого поля. Этот метод позволяет свести выделение к минимуму за счет повторного использования ранее созданных объектов. Он также позволяет вам «исправлять» объекты, преднамеренно перезаписывая их с помощью JSON, который содержит только небольшое подмножество полей.

Предупреждение. JSON Serializer API поддерживает MonoBehaviour и ScriptableObject. подклассы, а также простые структуры и классы. Однако при десериализации JSON в подклассы MonoBehaviour или ScriptableObject необходимо использовать FromJsonOverwrite. Если вы попытаетесь использовать FromJson, Unity выдаст исключение, поскольку такое поведение не поддерживается.

Поддерживаемые типы

JSON Serializer API поддерживает любой подкласс MonoBehaviour , подкласс ScriptableObject , а также простой класс или структуру с [Serializable] . Когда вы передаете объект стандартному сериализатору Unity для обработки, применяются те же правила и ограничения, что и в Инспекторе: Unity сериализует только поля; и такие типы, как Dictionary<> , не поддерживаются.

Unity не поддерживает передачу других типов напрямую в API, таких как примитивные типы или массивы. Если вам нужно преобразовать их, оберните их в какой-нибудь класс или struct .

Только в редакторе есть параллельный API, EditorJsonUtility, который позволяет сериализовать любой объект, производный от UnityEngine.Object как в JSON, так и из него. Это создает JSON, который содержит те же данные, что и YAML-представление объекта.

JsonUtility и EditorJsonUtility — это служебные классы для сериализации объектов в JSON и обратно. строковый формат с использованием правил сериализации Unity. В тех случаях, когда необходимо манипулировать данными JSON с помощью кода или сериализовать структуры данных, которые не поддерживает сериализация Unity, вы можете использовать библиотеку .NET JSON общего назначения в качестве дополнения к JsonUtility API.

Производительность

Эталонные тесты показывают, что JsonUtility работает значительно быстрее, чем популярные решения .NET JSON, хотя в некоторых случаях этот класс предоставляет меньше функций.

Использование памяти для сборки мусора (GC) минимально:

  • ToJson выделяет память GC только для возвращаемой строки.
  • FromJson выделяет память GC только для возвращаемого объекта, а также для любых необходимых подобъектов (например, если вы десериализуете объект, содержащий массив, то Unity выделяет память GC для массива).
  • FromJsonOverwrite выделяет память GC только по мере необходимости для записанных полей (например, строк и массивов). Это означает, что Unity вообще не выделяет память GC, если все поля, перезаписываемые JSON, имеют тип значения.

Вы можете использовать JsonUtility API из фонового потока. Однако, как и в случае с любым многопоточным кодом, будьте осторожны, чтобы не получить доступ к объекту или не изменить его в одном потоке, пока другой поток сериализует или десериализует его.

Управление выводом ToJson()

Метод ToJson поддерживает красивую печать вывода JSON. По умолчанию он отключен, но вы можете включить его, передав true в качестве второго параметра.

Вы можете исключить поля из вывода, используя атрибут [NonSerialized] .

Использование FromJson() с неизвестными типами

Если вы заранее не знаете тип объекта, десериализуйте JSON в класс или структуру, содержащую «общие» поля, а затем используйте значения этих полей, чтобы определить, какой фактический тип вам нужен. Затем выполните десериализацию во второй раз в этот тип.

Защита контента

Пока есть возможность использовать шифрование во время передачи ваших ассетов, пока они не добрались до получателя, у вас всё ещё есть возможность вернуть свой контент обратно. Например, есть инструменты, позволяющие сохранять 3D данные на уровне драйверов, позволяя пользователям извлекать модели и текстуры во время их отправки на обработку вашей видеокартой. С этой целью мы и решили дать возможность вашим пользователям извлекать нужные им ассеты из вашей игры.

Однако, если хотите, вы можете использовать и свой собственный способ шифрования данных для AssetBundle файлов.

Одним из способов добиться этого, является использование TextAsset типа для хранения ваших данных в байтах. Можно зашифровать нужные вам файлы, сохранив их с расширением .bytes, которое Unity будет воспринимать как TextAsset тип. После импортирования в редактор, данные файлы будут включены в ваши AssetBundles как TextAssets и размещены на сервере. Затем на стороне клиента будет скачан нужный AssetBundle, из TextAsset типов файлов которого будут извлечены необходимые клиенту данные. При таком подходе будут шифроваться не сами AssetBundles, а лишь TextAsset файлы, находящиеся в них.

string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d"; IEnumerator Start () < while (!Caching.ready) yield return null; // Start a download of the encrypted assetbundle WWW www = new WWW.LoadFromCacheOrDownload (url, 1); // Wait for download to complete yield return www; // Load the TextAsset from the AssetBundle TextAsset textAsset = www.assetBundle.Load("EncryptedData", typeof(TextAsset)); // Get the byte data byte[] encryptedData = textAsset.bytes; // Decrypt the AssetBundle data byte[] decryptedData = YourDecryptionMethod(encryptedData); // Use your byte array. The AssetBundle will be cached >

В качестве альтернативы можно полностью зашифровать AssetBundles в хранилище и затем скачать его путём использования WWW класса. До тех пор, пока ваши файлы хранятся на сервере в качестве бинарных данных, они могут иметь любое расширение. Как только нужный AssetBundle будет скачан, вам нужно будет декодировать данные, используя свойство .bytes вашего WWW экземпляра, чтобы получить расшифрованные данные из AssetBundle и воссоздать из памяти AssetBundle, используя AssetBundle.CreateFromMemory.

string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d"; IEnumerator Start () < // Start a download of the encrypted assetbundle WWW www = new WWW (url); // Wait for download to complete yield return www; // Get the byte data byte[] encryptedData = www.bytes; // Decrypt the AssetBundle data byte[] decryptedData = YourDecryptionMethod(encryptedData); // Create an AssetBundle from the bytes array AssetBundleCreateRequest acr = AssetBundle.CreateFromMemory(decryptedData); yield return acr; AssetBundle bundle = acr.assetBundle; // You can now use your AssetBundle. The AssetBundle is not cached. >

Преимущество второго подхода в сравнении с первым в том, что вы можете использоваться любой метод (кроме AssetBundles.LoadFromCacheOrDownload) для передачи своих байтов и данных в качестве закодированных — например сокеты в плагине. Минусом здесь будет то, что данные не будут кешироваться при использовании автоматического кеширования Unity. Можно добавить любые проигрыватели, кроме WebPlayer-а, который должен быть загружен вручную с вашего жёсткого диска с использованием AssetBundles.CreateFromFile

В качестве третьего способа будет неплохо взять лучшее из двух других, путём хранения самого AssetBundle в качестве TextAsset в других, нормальных AssetBundles. Не закодированный AssetBundle, содержащий в себе закодированный будет кешироваться. Оригинальный AssetBundle может быть затем загружен в память, декодирован и инстанциирован, используяAssetBundle.CreateFromMemory.

string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d"; IEnumerator Start () < while (!Caching.ready) yield return null; // Start a download of the encrypted assetbundle WWW www = new WWW.LoadFromCacheOrDownload (url, 1); // Wait for download to complete yield return www; // Load the TextAsset from the AssetBundle TextAsset textAsset = www.assetBundle.Load("EncryptedData", typeof(TextAsset)); // Get the byte data byte[] encryptedData = textAsset.bytes; // Decrypt the AssetBundle data byte[] decryptedData = YourDecryptionMethod(encryptedData); // Create an AssetBundle from the bytes array AssetBundleCreateRequest acr = AssetBundle.CreateFromMemory(decryptedData); yield return acr; AssetBundle bundle = acr.assetBundle; // You can now use your AssetBundle. The wrapper AssetBundle is cached >

Проблема с Шифрованием JSON

Author24 — интернет-сервис помощи студентам

Есть две сцены (Меню и игра)
В меню есть скрипт, который сохраняет и загружает игру, обращаясь к скрипту сохранения/загрузки а уже этот обращаеться к скрипту, который это кодирует и декдирует.
Цепь такая: Главный скрипт -> Скрипт Save/Load -> Скрипт шифрования

Так вот всё работает прекрасно, НО на второй сцене (Игре), если вызвать функцию сохранения или загрузки — ничего не произойдёт и если перейти обратно из игры в меню (По UI кнопке), то мне напишет в консоль — «Key Not Exist»

Главный скрипт (Меню) (Так-же и в скрипте, который уже в ИГРЕ находится)

1 2 3
[SerializeField] private ALL_SaveAndLoadFromJSON SaveAndLoad; //Ссылка на скрипт Save/Load SaveAndLoad.Save(); //Сохранение SaveAndLoad.Load(); //Загрузка

Скрипт Save/Load

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
public class ALL_SaveAndLoadFromJSON : MonoBehaviour { [SerializeField] private ALL_AesCryptJSON_Logic aesEncrypt; //Шифрование public Saves saves; public class Saves { //Тут много переменных с данными для сохранения //Например public int Money; public int Score; public bool isMusic; public bool isSound; } //Сохранение в JSON public void Save() { string json = JsonUtility.ToJson(saves); byte[] encryptedBytes = this.aesEncrypt.Encrypt(json); EncryptedGameCoreStruct encryptedGameCore = new EncryptedGameCoreStruct() { data = encryptedBytes, }; string encryptedJson = JsonUtility.ToJson(encryptedGameCore); File.WriteAllText(Path.Combine(Application.persistentDataPath + "/Save.json"), encryptedJson); } //Выгрузка сохранений из JSON public void Load() { string encryptedJson = File.ReadAllText(Application.persistentDataPath + "/Save.json"); byte[] encryptedBytes = JsonUtility.FromJsonEncryptedGameCoreStruct>(encryptedJson).data; string json = aesEncrypt.Decrypt(encryptedBytes); saves = JsonUtility.FromJsonSaves>(json); } }

Скрипт Шифрования

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
public class ALL_AesCryptJSON_Logic : MonoBehaviour { public byte[] Encrypt(string str) { byte[] encryptedBytes; using (Aes aes = Aes.Create()) { aes.GenerateKey(); aes.GenerateIV(); ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); using (MemoryStream ms = new MemoryStream()) { using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) { using (StreamWriter sm = new StreamWriter(cs)) { sm.Write(str); } } encryptedBytes = ms.ToArray(); } using (SHA256 sha = SHA256.Create()) { byte[] bytes = sha.ComputeHash(encryptedBytes); string hash = BitConverter.ToString(bytes).Replace(oldValue:"-", newValue:""); AesCryptoParametersStruct c = new AesCryptoParametersStruct { key = aes.Key, iv = aes.IV }; SaveEncryptParameters(c, hash); } } return encryptedBytes; } public string Decrypt(byte[] encryptedBytes) { AesCryptoParametersStruct c = LoadEncryptParameters(encryptedBytes); string decryptedString; using (Aes aes = Aes.Create()) { aes.Key = c.key; aes.IV = c.iv; ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); using (MemoryStream ms = new MemoryStream(encryptedBytes)) { using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read)) { using (StreamReader sr = new StreamReader(cs)) { decryptedString = sr.ReadToEnd(); } } } } return decryptedString; } public void SaveEncryptParameters(AesCryptoParametersStruct c, string key) { string json = JsonUtility.ToJson(c); PlayerPrefs.SetString(key, json); } public AesCryptoParametersStruct LoadEncryptParameters(byte[] encryptedBytes) { string key; using (SHA256 sha = SHA256.Create()) { byte[] hash = sha.ComputeHash(encryptedBytes); key = BitConverter.ToString(hash).Replace(oldValue:"-", newValue:""); } if (!PlayerPrefs.HasKey(key)) { throw new PlayerPrefsException(error: "Key Not Exist"); } string json = PlayerPrefs.GetString(key); PlayerPrefs.DeleteKey(key); return JsonUtility.FromJsonAesCryptoParametersStruct>(json); } }

Структура Шифрования

1 2 3 4 5 6 7 8 9 10 11 12 13 14
namespace Structs { [System.Serializable] public struct AesCryptoParametersStruct { public byte[] key; public byte[] iv; } [System.Serializable] public struct EncryptedGameCoreStruct { public byte[] data; } }

Как расшифровать этот JSON?

Есть JSON не могу расшифровать. Чем он зашифрован? Вроде base64, но расшифровать не получается. Как расшифровать этот JSON?

Отслеживать
73.4k 12 12 золотых знаков 93 93 серебряных знака 182 182 бронзовых знака
задан 22 мая 2021 в 18:58
139 1 1 серебряный знак 11 11 бронзовых знаков

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Это AES — простой и мощный метод шифрования и дешифрования.

Есть например на JS библа для этого

Однако для дешифровки нужен ключ, коего тут не предоставлено.

Что представлено как раз в той же библиотеке:

var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase"); ^^^^^^^^^^^^^^^ ключ для шифрования и расшифровки в последствии ​ encrypted.key > "74eb593087a982e2a6f5dded54ecd96d1fd0f3d44a58728cdcd40c55227522223 "; ​ encrypted.iv > "7781157e2629b094f0e3dd48c4d786115"; ​ encrypted.salt > "7a25f9132ec6a8b34"; ​ encrypted.ciphertext > "73e54154a15d1beeb509d9e12f1e462a0"; ​ encrypted > "U2FsdGVkX1+iX5Ey7GqLND5UFUoV0b7rUJ2eEvHkYqA="; ^^^^^^^^^^--- указание на этот метод шифрования 

Добавить комментарий

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