Assetの暗号化について

  • 59
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

はじめに

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」ではサポートされていないようです。

やってみた

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

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

現在Android端末にて動作を確認中なのですが、うまく動作していないようです。何か分かり次第こちらにて共有させて頂こうと思います。

Android、iOS、WebPlayerにて動作を確認したところ、問題なく動いているようです。
確認の仕方にミスがあったようです。