유니티 json데이터 암호화하는법(AES암호화방식)
- 목차
728x90
먼저 json이란?
직렬화 데이터로서 서버연동등과 같은 데이터교환에 유용하게 쓸수 있는 데이터 타입이다.
다만 아무래도 Json도 보안에는 취약한 편이다. 암호화등을 하지않는 이상 그냥 값변경이 가능하기 때문이다.
물론 민감한 정보같은건 서버에 저장하거나 DB, Addressable등을 이용해서 관리하긴 하지만
해당 예시에서는 없다고 가정하고 로컬에서 암호화를 시켜보았다.
그래서 이 해당 글은 그 데이터를 암호화하고 다시 복호화해서 불러오는 과정을 담아보았다.
완벽하지는 않아서 보고 참고정도만 해주시면 좋겠습니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System;
[Serializable]
public class PlayerStat
{
public string name = "";
public float Level = 0;
public float Exp = 0;
public float PlayerHealth = 0;
public float Health = 0;
}
[Serializable]
public class EnemyStat
{
public float EnemyHealth = 0;
public float damage = 0;
public float Health = 0;
}
[Serializable]
public class Itemdata
{
public string itemName = "";
public float Health = 0;
public int damage = 0;
public float dot = 0;
public float sight = 0;
}
[Serializable]
public class WeaponData
{
public int damage = 0;
}
public class DataManager : MonoBehaviour
{
public static DataManager Inst;
private static readonly byte[] EncryptionKey = new byte[]
{
// 32바이트(256비트) 암호화 키
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01
};
private byte[] IV = new byte[]
{
// 16바이트(128비트) 암호화 IV
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10
};
private void Start()
{
SaveData();
}
//여기다가 var타입으로 만들고 SaveToJson방식으로 저장시킬거임
private void InitializeData()
{
var playerStat = new PlayerStat
{
name = "",
Level = 1,
Exp = 0,
Health = 1000,
PlayerHealth = 1000
};
var enemyStat1 = new EnemyStat
{
EnemyHealth = 100,
damage = 30,
Health = 100
};
var enemyStat2 = new EnemyStat
{
EnemyHealth = 70,
damage = 20,
Health = 70
};
var enemyStat3 = new EnemyStat
{
EnemyHealth = 50,
damage = 40,
Health = 50
};
var potion = new Itemdata
{
itemName = "Potion",
Health = 30
};
var adrophine = new Itemdata
{
itemName= "adrophine",
damage=30,
dot=180
};
var weapon = new WeaponData { damage = 30 };
SaveToJsonEncrypted(adrophine, "Itemdata.json");
SaveToJsonEncrypted(potion, "Itemdata.json");
SaveToJsonEncrypted(playerStat, "PlayerStat.json");
SaveToJsonEncrypted(enemyStat1, "EnemyStat1.json");
SaveToJsonEncrypted(enemyStat2, "EnemyStat2.json");
SaveToJsonEncrypted(enemyStat3, "EnemyStat3.json");
SaveToJsonEncrypted(weapon, "WeaponData.json");
}
//자동으로 저장시켜줄거임
private void SaveToJsonEncrypted<T>(T data, string fileName)
{
string jsonData = JsonConvert.SerializeObject(data);
byte[] encryptedData = Encrypt(jsonData);
// 암호화된 데이터의 길이를 저장
int encryptedDataLength = encryptedData.Length;
// 저장할 데이터 배열 생성 (길이 정보 + 암호화된 데이터)
byte[] savedData = new byte[4 + encryptedDataLength];
// 길이 정보를 바이트 배열로 변환하여 저장
byte[] lengthBytes = BitConverter.GetBytes(encryptedDataLength);
Buffer.BlockCopy(lengthBytes, 0, savedData, 0, 4);
// 암호화된 데이터를 저장
Buffer.BlockCopy(encryptedData, 0, savedData, 4, encryptedDataLength);
string filePath = GetFilePath(fileName);
File.WriteAllBytes(filePath, savedData);
//Debug.Log("암호화된 데이터를 저장했습니다: " + filePath);
}
//자동으로 로딩시킬거임
private T LoadFromJsonEncrypted<T>(string fileName)
{
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
string filePath = GetFilePath(fileName);
byte[] savedData = File.ReadAllBytes(filePath);
if (savedData.Length < 4)
{
Debug.LogError("암호화된 데이터의 길이 정보가 올바르지 않습니다.");
return default(T);
}
// 저장된 데이터 배열에서 길이 정보를 읽어옴
int encryptedDataLength = BitConverter.ToInt32(savedData, 0);
if (encryptedDataLength != savedData.Length - 4)
{
Debug.LogError("암호화된 데이터의 길이가 올바르지 않습니다.");
return default(T);
}
// 길이 정보를 제외한 실제 암호화된 데이터 배열 생성
byte[] encryptedData = new byte[encryptedDataLength];
Buffer.BlockCopy(savedData, 4, encryptedData, 0, encryptedDataLength);
string decryptedJsonData = Decrypt(encryptedData); // 복호화된 JSON 데이터를 가져옵니다.
T data = JsonConvert.DeserializeObject<T>(decryptedJsonData);
return data;
}
//해당 코드를 암호화 시킴
private byte[] Encrypt(string data)
{
byte[] rawData = Encoding.UTF8.GetBytes(data);
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = EncryptionKey;
aesAlg.IV = IV;
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, aesAlg.CreateEncryptor(), CryptoStreamMode.Write))
{
csEncrypt.Write(rawData, 0, rawData.Length);
csEncrypt.FlushFinalBlock();
byte[] encryptedData = msEncrypt.ToArray();
return encryptedData;
}
}
}
}
//해당 코드를 다시 복호화 시킬거임
private string Decrypt(byte[] encryptedData)
{
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = EncryptionKey;
aesAlg.IV = IV;
aesAlg.IV = IV;
using (MemoryStream msDecrypt = new MemoryStream())
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV), CryptoStreamMode.Write))
{
csDecrypt.Write(encryptedData, 0, encryptedData.Length);
csDecrypt.FlushFinalBlock();
}
byte[] decryptedBytes = msDecrypt.ToArray();
return Encoding.UTF8.GetString(decryptedBytes).TrimEnd('\0');
}
}
}
string GetFilePath(string fileName)
{
return Path.Combine(Application.dataPath+"/StreamingAssets", fileName);
}
private void SaveData()
{
PlayerStat playerStat = LoadFromJsonEncrypted<PlayerStat>("PlayerStat.json");
SaveToJsonEncrypted(playerStat, "PlayerStat.json");
EnemyStat enemyStat1 = LoadFromJsonEncrypted<EnemyStat>("EnemyStat1.json");
SaveToJsonEncrypted(enemyStat1, "EnemyStat1.json");
EnemyStat enemyStat2 = LoadFromJsonEncrypted<EnemyStat>("EnemyStat2.json");
SaveToJsonEncrypted(enemyStat2, "EnemyStat2.json");
EnemyStat enemyStat3 = LoadFromJsonEncrypted<EnemyStat>("EnemyStat3.json");
SaveToJsonEncrypted(enemyStat3, "EnemyStat3.json");
WeaponData weaponData = LoadFromJsonEncrypted<WeaponData>("WeaponData.json");
Debug.Log("WeaponDamage:" + weaponData.damage);
SaveToJsonEncrypted(weaponData, "WeaponData.json");
Itemdata potion = LoadFromJsonEncrypted<Itemdata>("Itemdata.json");
SaveToJsonEncrypted(potion, "Itemdata.json");
Itemdata adrophine = LoadFromJsonEncrypted<Itemdata>("Itemdata.json");
SaveToJsonEncrypted(adrophine, "Itemdata.json");
}
}
좀 많이 길긴하다
그 이유는 암호화를 시킬 키를 만들어주고 그걸 바탕으로 암호화를 하고 다시 복호화를 시키고 읽어오는 과정을 하기 때문이다.
저렇게 코드를 짜놓고 실행시키면?
다음과 같이 정상적으로 작동함을 확인할 수 있다.
또한 기존 Json데이터는 그대로 보이는 반면에
와 같이 암호화되어서 안보이는것을 알수 있다.
728x90
'유니티,Unity,C#' 카테고리의 다른 글
유로 Assets DamageNumbersPro 리뷰 (1) | 2023.10.29 |
---|---|
오브젝트 풀링(원하는 스폰지역을 직접 만들어서 넣어주고 랜덤으로 소환) (0) | 2023.06.04 |
몬스터를 소환하고 정해진 루트로 이동하게 하는 스크립트 (0) | 2023.04.24 |
몬스터가 정해진 루트로 이동하는 스크립트 (0) | 2023.01.05 |
Unity Dotween(글씨가 쳐지는듯한 효과 만들기) (0) | 2022.12.28 |