GitHub
C#
Unity
セキュリティ
暗号

Unity(C#) で「正しい」暗号化処理をするライブラリを作成しました

概要

Unity(C#)において、共通鍵暗号の代表格であるAES暗号(正確にはAES暗号ではなくRijndael暗号)公開鍵暗号の代表格であるRSA暗号、それぞれ手軽に実装でき、セキュアな(解読されづらい)ものになるようにしたライブラリを公開しました。
UnityCipher
unitypackageをご希望の方はreleasesからダウンロードできますのでこちらからダウンロードしてください UnityCipher Releases

使い方

詳しい使い方はUnityCipher/Examples/ 以下にサンプルがありますので、こちらを確認してください。

また、ライブラリのメソッドを使う場合、using UnityCipherを追加することで使用することができます。

AES暗号を用いる場合

暗号化

以下のようなメソッドを呼び出すことで暗号化することができます。

string encrypted = RijndaelEncryption.Encrypt(planeText, passwordText);

こうすることで暗号化されたもの(encrypted)を取得することができます。
また、Encryptメソッドの第一引数である、planeTextbyte[]を指定することもでき、この場合、暗号化されたbyte[]を受け取ります。(以下を参考)

byte[] encrypted = RijndaelEncryption.Encrypt(planeBinary, passwordText);

復号

以下のようなメソッドを呼び出すことで復号することができます。

string planeText = RijndaelEncryption.Decrypt(encryptedText, passwordText);

暗号化されたものをうまく復号することができれば復号されたもの(planeText)を取得することができます。
Decryptメソッドの第一引数である、encryptedTextには暗号化されたbyte[]を指定することもでき、この場合、うまく復号できれば復号されたされたbyte[]を受け取ります。(以下を参照)

byte[] planeBinary = RijndaelEncryption.Decrypt(encryptedBinary, passwordText);

RSA暗号を用いる場合

公開鍵と秘密鍵のペアの作成

まずは以下のようなメソッドを呼び出すことで公開鍵と秘密鍵をそれぞれ作成します。

KeyValuePair<string, string> publicAndPrivateKeyValuePair = RSAEncryption.GenrateKeyPair(int keySize);

このとき、引数に設定したkeySizeに設定した値の大きさの公開鍵、秘密鍵が生成されます。指定できるkeySizeの値は512~16384の間の8bit単位での数字(8の倍数)になります。
詳しくはこちらを参照してください。
RSACryptoServiceProvider.KeySize Property
ここで指定する値が大きくなればなるほど、生成される公開鍵、秘密鍵の長さが大きくなり、よりセキュアなものになりますが、同時に暗号化、復号処理にかかる時間も増大します。
生成された公開鍵、秘密鍵はKeyValuePair<string, string>の形(publicAndPrivateKeyValuePair)で取得でき、それぞれKeyが公開鍵、Valueが秘密鍵となります。

暗号化

以下のようなメソッドを呼び出すことで暗号化することができます。

string encrypted = RSAEncryption.Encrypt(planeText, publicKey);

上記で生成した公開鍵(publicKey)を第二引数に指定することでRSA暗号化された暗号文(encrypted)を取得することができます。
Encryptの第一引数である、planeTextbyte[]を指定することもでき、この場合、暗号化されたbyte[]を受け取ります。(以下を参照)

byte[] encrypted = RSAEncryption.Encrypt(planeBinary, publicKey);

復号

以下のようなメソッドを呼び出すことで暗号化することができます。

string planeText = RSAEncryption.Decrypt(encryptedText, privateKey);

上記で生成した公開鍵(privateKey)を第二引数に指定することで、うまく復号できれば復号されたもの(planeText)を取得することができます。
Decryptの第一引数である、planeTextbyte[]を指定することもでき、byte[]を指定することもでき、この場合、うまく復号できれば復号されたされたbyte[]を受け取ります。(以下を参照)

byte[] planeBinary = RSAEncryption.Decrypt(encryptedBinary, privateKey);

特徴

このライブラリの特徴として

  • シンプルに使うことができます。
  • 強固なセキュリティで暗号化しています。

以上のような特徴があります。

強固なセキュリティとは?
なお、[RSA暗号](https://ja.wikipedia.org/wiki/RSA%E6%9A%97%E5%8F%B7)はスタンダードなものを使用しているため、今回、詳しい話は省略します。

### よくある話
AES暗号を実装する場合、<font color="#FF0000">平文、パスワード、Salt、IV(初期ベクター)</font>という4種類の要素を設定する必要があります。そして、SaltとIVを定数として設定してしまうことが非常によくあります。しかし、本来、AES暗号の特徴として、<font color="#FF0000">「同じ平文、同じパスワードであっても、暗号化するたびに暗号文が変わる」</font>という特徴があります。
しかし、<font color="#FF0000">IVとソルトを定数であるとこの特徴が全く活きなくなります。</font>(つまり、同じ平文、同じパスワードだと毎回同じ暗号文になる)
実際の運用において、このようなSaltとIVを定数として用いられている場合は非常に多くあります。

### 仕様
今回のライブラリでは、AES暗号において、暗号化するたびにSaltとIVを生成しています。Salt + IV + 暗号文をつなげた```byte[]```を生成し、この```byte[]```を取得できるようにしています。(詳しくはこちら)
これにより、<font color="#FF0000">「同じ平文、同じパスワードであっても、暗号化するたびに暗号文が変わる」</font>ようにしています。

なお、上記の仕様はすでに挙げましたので、よりセキュアに運用したい場合、順番を変えたり、bitのルールを変える、などの独自ルールにすることで対応することもできます。

# 参考・関連
 * [Data_Encryption_Standard](https://ja.wikipedia.org/wiki/Data_Encryption_Standard)
 * [Advanced_Encryption_Standard](https://ja.wikipedia.org/wiki/Advanced_Encryption_Standard)
 * [DES暗号化](http://www.atmarkit.co.jp/ait/articles/1505/21/news030.html)
 * [暗号利用モード](https://ja.wikipedia.org/wiki/%E6%9A%97%E5%8F%B7%E5%88%A9%E7%94%A8%E3%83%A2%E3%83%BC%E3%83%89)
 * [C#(.NET Framework)のAESを使ってファイルを暗号化してみる](https://hibara.org/blog/2011/02/20/c-sharp-net-framework-aes/)
 * [Visual Studio C#でファイルを暗号化してみる](http://qiita.com/hibara/items/c9096376b1d7b5c8e2ae)
 * [プログラマ暗号入門](https://qiita.com/asksaito/items/1793b8d8b3069b0b8d68)