#はじめに#
Assetの暗号化について、自分なりに調べたものをまとめてみます。
#Assetを暗号化するには#
暗号化するAssetをTextAssetとして扱い、byte配列を操作(暗号化、及び復号化)することになります。
#AssetをTextAssetとして扱う#
詳しくは以下のドキュメントの下部、[バイナリ データ]以下に記載されています。
暗号化したいAssetの拡張子を[.bytes]に変更するだけでTextAssetとして読み込み、直接バイナリデータを扱うことができるようです。思ってたより簡単なことでした。
#TextAssetを暗号化#
C#ではAESによる暗号化ライブラリを使用する事が可能なので、そちらを使用する事にしました。
以下のサイトを参考にしました。
実は、こちらの記事に辿り着く前に、
こちらの記事を参考にしていたのですが、こちらの方法だとエラーが発生してしまい、頭を抱えた経緯がありました.....。
調べたところ、UnityAnswersでもトピックが立てられていました。
「.NET 2.0 subset」ではサポートされていないようです。
#やってみた#
using UnityEngine;
using System;
using System.IO;
using System.Text;
using System.Collections;
using System.Security.Cryptography;
public class AesCryptography
{
// 256bit(32byte)のInitVector(初期ベクタ)とKey(暗号キー)
private const string AesInitVector = @"hogehogehogehogehogehogehogehoge";
private const string AesKey = @"piyopiyopiyopiyopiyopiyopiyopiyo";
private const int BlockSize = 256;
private const int KeySize = 256;
/// <summary>
/// 暗号化スクリプト
/// </summary>
/// <returns>byte[] 暗号化したbyte列</returns>
public byte[] Encrypt( byte[] binData )
{
RijndaelManaged myRijndael = new RijndaelManaged();
myRijndael.Padding = PaddingMode.Zeros;
myRijndael.Mode = CipherMode.CBC;
myRijndael.KeySize = KeySize;
myRijndael.BlockSize = BlockSize;
byte[] key = new byte[0];
byte[] InitVector = new byte[0];
key = System.Text.Encoding.UTF8.GetBytes( AesKey );
InitVector = System.Text.Encoding.UTF8.GetBytes( AesInitVector );
ICryptoTransform encryptor = myRijndael.CreateEncryptor( key, InitVector );
MemoryStream msEncrypt = new MemoryStream();
CryptoStream csEncrypt = new CryptoStream( msEncrypt, encryptor, CryptoStreamMode.Write );
byte[] src = binData;
// 暗号化する
csEncrypt.Write( src, 0, src.Length );
csEncrypt.FlushFinalBlock();
byte[] dest = msEncrypt.ToArray();
return dest;
}
/// <summary>
/// 複合化スクリプト
/// </summary>
/// <returns>byte[] 複合化したbyte列</returns>
public byte[] Decrypt ( byte[] binData )
{
RijndaelManaged myRijndael = new RijndaelManaged();
myRijndael.Padding = PaddingMode.Zeros;
myRijndael.Mode = CipherMode.CBC;
myRijndael.KeySize = KeySize;
myRijndael.BlockSize = BlockSize;
byte[] key = new byte[0];
byte[] InitVector = new byte[0];
key = System.Text.Encoding.UTF8.GetBytes( AesKey );
InitVector = System.Text.Encoding.UTF8.GetBytes( AesInitVector );
ICryptoTransform decryptor = myRijndael.CreateDecryptor( key, InitVector );
byte[] src = binData;
byte[] dest = new byte[ src.Length ];
MemoryStream msDecrypt = new MemoryStream( src );
CryptoStream csDecrypt = new CryptoStream( msDecrypt, decryptor, CryptoStreamMode.Read );
// 複号化する
csDecrypt.Read( dest, 0, dest.Length );
return dest;
}
}
hoge
とかpiyo
と書いてある場所は任意に作成したものを使用して下さい。
#エディター上でできるようにした#
選択中のAssetを暗号化、及び復号化し、任意の場所に変換後のAssetを保存するエディタースクリプトを書きました。
public class AssetCryptography
{
private const string SaveExtension = ".bytes";
/// <summary>
/// 暗号化スクリプト
/// </summary>
[ MenuItem("Assets/Cryptography/Aes/Encrypt")]
static void AssetEncrypt ()
{
//Assetをbytes拡張子で保存したものを取得
TextAsset obj = (TextAsset)Selection.activeObject;
AesCryptography aesCryptography = new AesCryptography();
byte[] encryptData = aesCryptography.Encrypt( obj.bytes );
//保存するパスを選択
string exportPath = EditorUtility.OpenFolderPanel( "保存するフォルダを選択してください", Application.dataPath, "" );
if( exportPath == null )
{
Debug.LogError( "選択時にエラーが発生しました" );
return;
}
// 暗号化したファイルを保存
File.WriteAllBytes( exportPath + "/" + obj.name + SaveExtension, encryptData );
}
/// <summary>
/// 復号化スクリプト
/// </summary>
[ MenuItem("Assets/Cryptography/Aes/Decrypt")]
static void AssetDecrypt ()
{
//Assetをbytes拡張子で保存したものを取得
TextAsset obj = (TextAsset)Selection.activeObject;
AesCryptography aesCryptography = new AesCryptography();
byte[] decryptData = aesCryptography.Decrypt( obj.bytes );
//保存するパスを選択
string exportPath = EditorUtility.OpenFolderPanel( "保存するフォルダを選択してください", Application.dataPath, "" );
if( exportPath == null )
{
Debug.LogError( "選択時にエラーが発生しました" );
return;
}
// 復号化したファイルを保存
File.WriteAllBytes( exportPath + "/" + obj.name + SaveExtension, decryptData );
}
}
こんな感じです。
#最後に#
記事中にまずい点等あれば指摘頂けると幸いです。
##追記##
Assetが暗号化、復号化されているかは、バイナリエディタにファイルを投げて確認していました(bz)。
現在Android端末にて動作を確認中なのですが、うまく動作していないようです。何か分かり次第こちらにて共有させて頂こうと思います。
Android、iOS、WebPlayerにて動作を確認したところ、問題なく動いているようです。
確認の仕方にミスがあったようです。