Unity でゲームの設定などを保存するのには PlayserPrefs を利用するのが一般的だと思うが、これは特に暗号化などせず保存されているようだ。
例えばスタンドアロン版 Mac であれば, ~/Library/Preferences/unity.会社名.プロジェクト名.plist に保存されており、Xcode をインストールしていればダブルクリックすればすぐ中身がわかってしまう。
編集されても良いデータであればそのままでも良いが、いじられたくないデータの場合は暗号化やハッシュ値によるチェックなどしたくなるだろう。という事で Unity の forum にあった PlayerPrefs Encryption を試しに使ってみた。
PlayerPrefs Encryption
最初に注意点だが、Encryption と名前にあるが暗号化をするわけではなく、チェックサムを利用して編集を難しくしている。見られたくないようなデータを保存するには向いてない。
フォーラムにある EncryptedPlayerPrefs クラスをプロジェクトの plugins ディレクトリなどに保存し, レスにある修正事項を適応させよう。
PlayerPrefs Encryptionusing UnityEngine;
using System.Collections;
using System.Security.Cryptography;
using System.Text;
public class EncryptedPlayerPrefs {
// Encrypted PlayerPrefs
// Written by Sven Magnus
// MD5 code by Matthew Wegner (from [url]http://www.unifycommunity.com/wiki/index.php?title=MD5[/url])
// Modify this key in this file :
private static string privateKey="9ETrEsWaFRach3gexaDr";
// Add some values to this array before using EncryptedPlayerPrefs
public static string[] keys;
public static string Md5(string strToEncrypt) {
UTF8Encoding ue = new UTF8Encoding();
byte[] bytes = ue.GetBytes(strToEncrypt);
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte[] hashBytes = md5.ComputeHash(bytes);
string hashString = "";
for (int i = 0; i < hashBytes.Length; i++) {
hashString += System.Convert.ToString(hashBytes[i], 16).PadLeft(2, '0');
}
return hashString.PadLeft(32, '0');
}
public static void SaveEncryption(string key, string type, string value) {
int keyIndex = (int)Mathf.Floor(Random.value * keys.Length);
string secretKey = keys[keyIndex];
//string check = Md5(type + "_" + privateKey + "_" + secretKey + "_" + value);
string check = Md5(key + "_" + type + "_" + privateKey + "_" + secretKey + "_" + value);
PlayerPrefs.SetString(key + "_encryption_check", check);
PlayerPrefs.SetInt(key + "_used_key", keyIndex);
}
public static bool CheckEncryption(string key, string type, string value) {
int keyIndex = PlayerPrefs.GetInt(key + "_used_key");
string secretKey = keys[keyIndex];
//string check = Md5(type + "_" + privateKey + "_" + secretKey + "_" + value);
string check = Md5(key + "_" + type + "_" + privateKey + "_" + secretKey + "_" + value);
if(!PlayerPrefs.HasKey(key + "_encryption_check")) return false;
string storedCheck = PlayerPrefs.GetString(key + "_encryption_check");
return storedCheck == check;
}
public static void SetInt(string key, int value) {
PlayerPrefs.SetInt(key, value);
SaveEncryption(key, "int", value.ToString());
}
public static void SetFloat(string key, float value) {
PlayerPrefs.SetFloat(key, value);
SaveEncryption(key, "float", Mathf.Floor(value*1000).ToString());
}
public static void SetString(string key, string value) {
PlayerPrefs.SetString(key, value);
SaveEncryption(key, "string", value);
}
public static int GetInt(string key) {
return GetInt(key, 0);
}
public static float GetFloat(string key) {
return GetFloat(key, 0f);
}
public static string GetString(string key) {
return GetString(key, "");
}
public static int GetInt(string key,int defaultValue) {
int value = PlayerPrefs.GetInt(key);
if(!CheckEncryption(key, "int", value.ToString())) return defaultValue;
return value;
}
public static float GetFloat(string key, float defaultValue) {
float value = PlayerPrefs.GetFloat(key);
if(!CheckEncryption(key, "float", Mathf.Floor(value*1000).ToString())) return defaultValue;
return value;
}
public static string GetString(string key, string defaultValue) {
string value = PlayerPrefs.GetString(key);
if(!CheckEncryption(key, "string", value)) return defaultValue;
return value;
}
public static bool HasKey(string key) {
return PlayerPrefs.HasKey(key);
}
public static void DeleteKey(string key) {
PlayerPrefs.DeleteKey(key);
PlayerPrefs.DeleteKey(key + "_encryption_check");
PlayerPrefs.DeleteKey(key + "_used_key");
}
}
使い方
基本的には通常の PlayerPrefs とほぼ同じです。使用する前にハッシュ key の設定を行うぐらいでしょうか。
// ここは各自適当に。
EncryptedPlayerPrefs.keys = new string[] {
"iDb0d", "1Dbaz", "0fbDp", "bepDb", "ag85z"
};
string key = "PlayerName";
string value = "Yudachi";
EncryptedPlayerPrefs.SetString (key, value);
PlayerPrefs.Save ();
このようにして値を保存すると、通常の値の他にチェックサム用の値も一緒に保存される。
値を直接変更しても、読み込みの際にハッシュ値をチェックしてエラーとなる。