WP TIPS に戻る

Triple DES でデータを暗号化する

Windows Phone7 の Silverlight で使用できる暗号化アルゴリズムは、Triple DES と AES を使用することが出来、文字列やバイナリ列などを暗号化してファイルに保存することが出来ます。
ここでは ProtectedData クラスを使用した Triple DES による暗号化を紹介します。

しかしこのクラスには大きな問題がありますので、本当に暗号化したい場合はエントロピー(パスワード)を付加して使用して下さい。

ProtectedData クラスを使用して Triple DES で暗号化する

System.Security.Cryptography.ProtectedData クラスを使用することで、簡単にバイト列の暗号化を行う事が出来ます。

using System.Security.Cryptography;

// 暗号化する文字列
string plaintext = "hello";

// 暗号化
byte[] protectedBytes = ProtectedData.Protect(Encoding.UTF8.GetBytes(plaintext), null);

// 復号化
byte[] unprotectedBytes = ProtectedData.Unprotect(protectedBytes, null);

// 文字列を取得する
string text = Encoding.UTF8.GetString(unprotectedBytes, 0, unprotectedBytes.Length);

ProtectedData.Protect で取得したバイト列をファイルに出力し、そのファイルからデータを読み込むときは注意が必要です。IsolatedStorageFileStream がパディングしてしまうようで、IsolatedStorageFileStream.Read をすると余計なバイト列が読み込みデータに付加されてしまい、復号化できません。
ファイルから読み込む場合は、以下のように IsolatedStorageFileStream.BaseStream から直接読み込んで下さい。

using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
    using (var stream = new IsolatedStorageFileStream(REG_INFO_FILE, FileMode.Open, FileAccess.Read, store))
    {
        using (var reader = new StreamReader(stream))
        {
            byte[] rawData = new byte[reader.Length];
            reader.Read(rawData, 0, Convert.ToInt16(byteStream.Length));

            byte[] safeData = ProtectedData.Unprotect(rawData, null);
         }
    }
}

ProtectedData クラスの問題点

ProtectedData クラスを使用すると Triple DES を用いた共有鍵方式(いわゆるパスワード)で、暗号化されます。
このパスワードは指定することが出来ず OS 側でパスワードを指定するので、どのようなパスワードを使用しているのか秘匿されます。逆アセンブルしてコード解析してもパスワードが分からないというのが利点で、Windows 2000 以降の OS であればログインしているユーザのパスワードが使用されるので、結果的に秘匿されます。

では翻って WP7 では・・・パスワードに「使用しているアプリの ProductID(GUID)」が使用されます。

ProductID は アプリのマニフェストファイル(WMAppManifest.xml) に記載されいるもので XAP のインストールパスにも使用されており、 Microsoft.Smartdevice.Connectivity.dll を使用すれば開発環境がインストールされている PC なら直ぐに見つけることが出来ます(というか WP7 端末内のデータファイルにもアクセスできる)、ので既知のパスワードと思って良いでしょう。

対策としては Protect メソッド第2引数でエントロピー(追加のバイト列) を追加する事で、ユニークさを与えることは出来ます。
ユーザが入力したパスワードをバイト列にして、エントロピーに指定するのは OK でしょう。が、コードを追って分かるようなバイト列なら意味がありません。

ということで、とりあえず ProtectedData クラスを使って IsolatedStorage 内のファイルを暗号化♪ と考えている方は、よく考えて使用して下さい。エントロピーを指定しないと、強固といえない暗号化を施してしまいます。

参考