[Unity]AESを使用してデータファイルを暗号化してみた。 

ゲーム開発

前回の記事ではデータファイルを作成してセーブ・ロード処理を実装しました。 
しかし、前回の実装だとデータファイルの暗号化がされていません。 
なので、今回はデータファイルを暗号化する方法を記載していきます。 

はじめに

この記事は前回の記事の続きになっています。

この記事での実装は以下のサイトを参考に実装しています。

【C#中級】 AES-256で暗号化・復号化する方法
C#でAES-256暗号するためのコードを実装してみました。System.Security.Cryptography.RijndaelManagedクラスと共通鍵を使えば暗号・復号化を簡単に行うことができます。

より詳しく解説されておりますので、こちらも参考にしていただければと思います。 

AES処理の実装 

AESの処理を行うプログラムになります。 
といっても、参考元のプログラムと内容はほとんど同じです。 

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public static class AESCipher {

    // 初期化ベクトル"<半角16文字(1byte=8bit, 8bit*16=128bit>"
    private const string AES_IV_256 = @"mER5Ve6jZ/F8CY%~";
    // 暗号化鍵<半角32文字(8bit*32文字=256bit)>
    private const string AES_Key_256 = @"kxvuA&k|WDRkzgG47yAsuhwFzkQZMNf3";

    /// <summary>
    /// 対称鍵暗号を使って文字列を暗号化する
    /// </summary>
    /// <param name="text">暗号化する文字列</param>
    /// <param name="iv">対称アルゴリズムの初期ベクター</param>
    /// <param name="key">対称アルゴリズムの共有鍵</param>
    /// <returns>暗号化された文字列</returns>
    public static string Encrypt(string text) {
        RijndaelManaged myRijndael = new RijndaelManaged();
        // ブロックサイズ(何文字単位で処理するか)
        myRijndael.BlockSize = 128;
        // 暗号化方式はAES-256を採用
        myRijndael.KeySize = 256;
        // 暗号利用モード
        myRijndael.Mode = CipherMode.CBC;
        // パディング
        myRijndael.Padding = PaddingMode.PKCS7;

        myRijndael.IV = Encoding.UTF8.GetBytes(AES_IV_256);
        myRijndael.Key = Encoding.UTF8.GetBytes(AES_Key_256);

        // 暗号化
        ICryptoTransform encryptor = myRijndael.CreateEncryptor(myRijndael.Key, myRijndael.IV);

        byte[] encrypted;
        using (MemoryStream mStream = new MemoryStream()) {
            using (CryptoStream ctStream = new CryptoStream(mStream, encryptor, CryptoStreamMode.Write)) {
                using (StreamWriter sw = new StreamWriter(ctStream)) {
                    sw.Write(text);
                }//using
                encrypted = mStream.ToArray();
            }//using
        }//using
        // Base64形式(64種類の英数字で表現)で返す
        return (System.Convert.ToBase64String(encrypted));
    }//Encrypt

    /// <summary>
    /// 対称鍵暗号を使って暗号文を復号する
    /// </summary>
    /// <param name="cipher">暗号化された文字列</param>
    /// <param name="iv">対称アルゴリズムの初期ベクター</param>
    /// <param name="key">対称アルゴリズムの共有鍵</param>
    /// <returns>復号された文字列</returns>
    public static string Decrypt(string cipher) {
        RijndaelManaged rijndael = new RijndaelManaged();
        // ブロックサイズ(何文字単位で処理するか)
        rijndael.BlockSize = 128;
        // 暗号化方式はAES-256を採用
        rijndael.KeySize = 256;
        // 暗号利用モード
        rijndael.Mode = CipherMode.CBC;
        // パディング
        rijndael.Padding = PaddingMode.PKCS7;

        rijndael.IV = Encoding.UTF8.GetBytes(AES_IV_256);
        rijndael.Key = Encoding.UTF8.GetBytes(AES_Key_256);

        ICryptoTransform decryptor = rijndael.CreateDecryptor(rijndael.Key, rijndael.IV);

        string plain = string.Empty;
        using (MemoryStream mStream = new MemoryStream(System.Convert.FromBase64String(cipher))) {
            using (CryptoStream ctStream = new CryptoStream(mStream, decryptor, CryptoStreamMode.Read)) {
                using (StreamReader sr = new StreamReader(ctStream)) {
                    plain = sr.ReadLine();
                }//using
            }//using
        }//using
        return plain;
    }//Decrypt

}//AESCipher

参考元のプログラムから変更した箇所は定数で宣言している文字列のみとなっています。

    // 初期化ベクトル"<半角16文字(1byte=8bit, 8bit*16=128bit>"
    private const string AES_IV_256 = @"mER5Ve6jZ/F8CY%~";
    // 暗号化鍵<半角32文字(8bit*32文字=256bit)>
    private const string AES_Key_256 = @"kxvuA&k|WDRkzgG47yAsuhwFzkQZMNf3";

AES処理の使用方法

前回の記事で作成したデータファイルのセーブ・ロード処理にAES処理を反映しました。 

using LitJson;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;

public static class ScoreData{

    private const string SAVE_PATH = "/Assets/Output/";//ファイルを保存するためのパス
    private const string FILE_NAME = "scoreData.dat";//保存するファイル名
    private const int DEFAULT_HIGH_SCORE = 15;

    public struct ScoreDataStruct { public int highScore; }//ハイスコアの値を保存する構造体
    public static ScoreDataStruct scoreDataStruct;

    /// <summary>
    /// ファイルパスの設定処理
    /// </summary>
    /// <returns>ファイルパス</returns>
    private static string FilePath() {
        string path = "";
        #if UNITY_EDITOR
            path = Directory.GetCurrentDirectory() + SAVE_PATH;
        #endif
        return path + FILE_NAME;
    }

    /// <summary>
    /// スコアデータの作成処理
    /// </summary>
    private static void ScoreDataCreate() {
        scoreDataStruct.highScore = DEFAULT_HIGH_SCORE;
        string jsonText = JsonMapper.ToJson(scoreDataStruct);
        ScoreDataSave(jsonText);
    }

    /// <summary>
    /// スコアデータの保存処理
    /// </summary>
    /// <param name="jsonText">保存するjsonText</param>
    private static void ScoreDataSave(string jsonText) {
        jsonText = AES.Encrypt(jsonText);//暗号化
        using (TextWriter tw = new StreamWriter(FilePath(), false, Encoding.UTF8))
            tw.Write(jsonText);
    }



    /// <summary>
    /// スコアデータの読み込み処理
    /// </summary>
    private static void ScoreDataLoad() {
        using (TextReader tr = new StreamReader(FilePath(), Encoding.UTF8)) {
            string jsonText = AES.Decrypt(tr.ReadToEnd());//複合化
            scoreDataStruct = JsonMapper.ToObject<ScoreDataStruct>(jsonText);
        } 
    }


    /// <summary>
    /// スコアデータの初期設定処理
    /// </summary>
    public static void ScoreDataInit() {
        if(File.Exists(FilePath())) {   //ファイルがある場合、ファイルを読み込む
            ScoreDataLoad();
        } else {                        //ファイルがない場合、ファイルを作成する
            ScoreDataCreate();
        }
    }

 

    /// <summary>
    /// スコアデータの更新処理
    /// </summary>
    /// <param name="highScore">ハイスコアの値</param>
    public static void ScoreDataUpdate(int highScore) {
        scoreDataStruct.highScore = highScore;
        string jsonText = JsonMapper.ToJson(scoreDataStruct);
        ScoreDataSave(jsonText);
    }
    
}

変更箇所

変更した箇所はScoreDataSave(string jsonText)とScoreDataLoad()の2か所になります。

ScoreDataSave(string jsonText)

json化した文字列をデータファイルとして保存する前に暗号化しています。

    /// <summary>
    /// スコアデータの保存処理
    /// </summary>
    /// <param name="jsonText">保存するjsonText</param>
    private static void ScoreDataSave(string jsonText) {
        jsonText = AES.Encrypt(jsonText);//暗号化
        using (TextWriter tw = new StreamWriter(FilePath(), false, Encoding.UTF8))
            tw.Write(jsonText);
    }

ScoreDataLoad()

読み込んだ暗号化データを使用する前に複合化しています。

    /// <summary>
    /// スコアデータの読み込み処理
    /// </summary>
    private static void ScoreDataLoad() {
        using (TextReader tr = new StreamReader(FilePath(), Encoding.UTF8)) {
            string jsonText = AES.Decrypt(tr.ReadToEnd());//複合化
            scoreDataStruct = JsonMapper.ToObject<ScoreDataStruct>(jsonText);
        } 
    }

プログラムの確認 

反映させたプログラムを起動してAES暗号化の処理を確認してみます。 

起動するとデータファイルが作成されます。 
(詳しくは前回の記事をご確認ください。)

作成されたデータファイルの中身を確認すると暗号化されているのが確認できます。 

暗号化前のデータファイル
暗号化後のデータファイル

最後に 

今回は、AESを使用した暗号化の方法をまとめてみました。 

簡単に実装できるので、暗号化の方法を検討している方の参考になれればと思います。 

コメント

タイトルとURLをコピーしました