Assetの暗号化について

#はじめに#
Assetの暗号化について、自分なりに調べたものをまとめてみます。

#Assetを暗号化するには#
暗号化するAssetをTextAssetとして扱い、byte配列を操作（暗号化、及び復号化）することになります。

#AssetをTextAssetとして扱う#
詳しくは以下のドキュメントの下部、[バイナリ データ]以下に記載されています。

http://docs-jp.unity3d.com/Documentation/Components/class-TextAsset.html

暗号化したいAssetの拡張子を[.bytes]に変更するだけでTextAssetとして読み込み、直接バイナリデータを扱うことができるようです。思ってたより簡単なことでした。

#TextAssetを暗号化#
C#ではAESによる暗号化ライブラリを使用する事が可能なので、そちらを使用する事にしました。

以下のサイトを参考にしました。

http://masa795.hatenablog.jp/entry/2013/04/19/102642

実は、こちらの記事に辿り着く前に、

http://programmers.high-way.info/cs/aes.html

こちらの記事を参考にしていたのですが、こちらの方法だとエラーが発生してしまい、頭を抱えた経緯がありました.....。
調べたところ、UnityAnswersでもトピックが立てられていました。

http://answers.unity3d.com/questions/193286/aes-encryption.html

「.NET 2.0 subset」ではサポートされていないようです。

#やってみた#

```csharp:AesCryptography
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を保存するエディタースクリプトを書きました。

```csharp:AssetCryptography.cs

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)。

<del>現在Android端末にて動作を確認中なのですが、うまく動作していないようです。何か分かり次第こちらにて共有させて頂こうと思います。</del>
Android、iOS、WebPlayerにて動作を確認したところ、問題なく動いているようです。
確認の仕方にミスがあったようです。