この記事は、SQLite に暗号化機能を加えた「SQLCipher」を(フリーで)Unity (Windows) 向け に DLL をコンパイルする方法を記録したものです。
- SQLiteUnityKit 用の SQLCipher を用意するには
- 環境設定
- OpenSSL のインストール
- SQLCipher のリポジトリーをクローン
- Makefile.msc の編集
- コンパイル
- コンパイルできた
- SQLiteUnityKit で使うためには
- 暗号化に対応しているかチェックする要点
- 使い方のポイント
- 参考
ここでの SQLCipher は、オープンソース版の「SQLCipher Community Edition」です。
SQLiteUnityKit 用の SQLCipher を用意するには
SQLiteUnityKit は、ネイティブな C ライブラリーを DllImport
で呼び出してデータベースを操作しています。
なので、SQLCipher もなるべくシンプルな DLL を作成します。(自分でコンパイルしてやる必要があるという意味です)さっぱりと「DllImport
を通じて定義されている関数を呼び出せるだけ」というライブラリーがゴールになっています。
Android のアプリにも対応させるなら .so ファイルも同様のものを作成してやる必要があります。「SQLCipher for Android Application Integration」で使い方を説明してくれていますが、JAVA を利用しているため、「SQLiteUnityKit」を基本にしたい身としては、不都合です……というか、今からつくる DLL と整合性がとれません。(なので、ここの記事がやりたいことになります。
Android 用の so ファイルのビルドは、こっちの記事を参照。
環境設定
不要かもしれない(けど、入れたもの)
OpenSSL のインストール
OpenSSL は公式からダウンロードして、自分でコンパイルしてもよいけど、以下のあたりの lib(ライブラリー)を参照するため用意する必要があります。ここでは環境設定のリンクからインストーラーを利用してインストールしました。(これだと全部用意してくれてる)
- libapps.lib
- libcrypto_static.lib
- libssl_static.lib
- ossltest.lib
- capi.lib
- libcrypto.def
- libssl.def
- libtestutil.lib
- padlock.lib
- dasync.lib
- libcrypto.lib
- libssl.lib
- openssl.lib
- uitest.lib
インストール設定は、すべてデフォルトで問題ないです。
Light を利用していないので、Light でいいかは知らないです。
ここでは以下の URL にインストールしました。あとの記事でも、この OpenSSL のパスを直接入力しているところがあるので、その部分は置き換えてください。
- C:\openssl_x64
- C:\openssl_x86
SQLCipher のリポジトリーをクローン
Visual Studio, Git Bash などなにを使ってもいいですが、ここでは Visual Studio を利用します。
Visual Studio のツール「x64/x86 Native Tools Command Prompt for VS 2019」を使って、あとでコンパイルするため、ここでは必須です。
「コードをクローンまたはチェックアウトする」から、リポジトリーをクローンします。
こんな感じで、OpenSSL と SQLCipher を利用する環境が整いました。
Makefile.msc の編集
Makefile は、コンパイルの条件設定を作成するファイルです。なので、詳しい詳細は作った人にしか正直わからないため、細かいミスや環境の違い等でうまく通らないと面倒になる部分です。(個人的には一番注意したいところ)
(x64/x86) の違いについて
つぎの「設定値の修正」の項目では、x64/x86 のコードを併記している部分があります。
どちらかのコードだけを書くようにして、コンパイルは別々にする必要があります。(クローンするリポジトリーを2つにしておくのもよいと思います)
設定値の修正
272, 275 行目(細かい行番号は以下を含めて、クローンされたバージョンによってズレてるかも)のコードを以下のように変更しました。
# 変更前 SQLITE3DLL = ******.dll # 変更後 SQLITE3DLL = sqlcipher.dll
283, 285 行目のコードを以下のように変更しました。
# 変更前 SQLITE3LIB = ******.lib # 変更後 SQLITE3LIB = sqlcipher.lib
293, 295 行目のコードを以下のように変更しました。
# 変更前 SQLITE3EXE = ******.exe # 変更後 SQLITE3EXE = sqlcipher.exe
306 行目のコードを以下のように変更しました。
# 変更前 SQLITE3EXEPDB = /pdb:sqlite3sh.pdb # 変更後 SQLITE3EXEPDB = /pdb:sqlciphersh.pdb
988, 989 行目のコードを以下のように「1」から「2」に変更しました。書かれている場所は、 (-DSQLITE_TEMP_STORE) で検索すると飛びやすい。
# 変更前 TCC = $(TCC) -DSQLITE_TEMP_STORE=1 RCC = $(RCC) -DSQLITE_TEMP_STORE=1 # 変更後 TCC = $(TCC) -DSQLITE_TEMP_STORE=2 RCC = $(RCC) -DSQLITE_TEMP_STORE=2
989 行目の下に以下のコードを書き足します。(書き換えではなくて、新しく書き加えます)
# Add -DSQLITE_HAS_CODEC to TCC and RCC TCC = $(TCC) -DSQLITE_HAS_CODEC RCC = $(RCC) -DSQLITE_HAS_CODEC
さらに、以下のコードも新しく書き加えます。(x86/x64 でどちらかを入れてください)
# Add OpenSSL include Path (x86) TCC = $(TCC) -IC:C:\openssl_x86\include RCC = $(RCC) -IC:C:\openssl_x86\include # Add OpenSSL include Path (x64) TCC = $(TCC) -IC:C:\openssl_x64\include RCC = $(RCC) -IC:C:\openssl_x64\include
最後に、以下のコードを新しく書き加えます。/LIBPATH:C:~
のコードは例のように同じ行で(1行)で書きます。
# Add OpenSSL Library path and Library filenames (x86) LTLIBPATHS = $(LTLIBPATHS) /LIBPATH:C:\openssl_x86\lib /LIBPATH:C:\openssl_x86\lib\VC LTLIBS = $(LTLIBS) capi.lib padlock.lib libcrypto.lib libssl.lib # Add OpenSSL Library path and Library filenames (x64) LTLIBPATHS = $(LTLIBPATHS) /LIBPATH:C:\openssl_x64\lib /LIBPATH:C:\openssl_x64\lib\VC LTLIBS = $(LTLIBS) capi.lib padlock.lib libcrypto.lib libssl.lib
If ICU support is enabled で検索して、その上に加えました
コンパイル
コンパイル用の「Native Tools Command Prompt for VS 2019」を起動します。x86/x64 のどちらかをで起動します。(念のため、管理者として実行しています)
- C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio 2019\Visual Studio Tools\VC
cd
で sqlcipher をクローンしたフォルダーに移動して、n make /f Makefile.msc
で編集した makefile を実行します。
cd "#リポジトリーのパス#" nmake /f Makefile.msc
エラーがでるとき
環境によって、以下のように openssl の include が開けないというエラーが出ることがあります。
sqlite3.c(24328): fatal error C1083: include ファイルを開けません。'openssl/rand.h':No such file or directory NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.24.28314\bin\HostX86\x86\cl.EXE"' : リターン コード '0x2' Stop.
うまく include のパスが追加できていないみたいです。こういうときは、コンパイルしているビット数にあわせて、次のフォルダーをプロジェクトに追加します。
- C:\openssl_x86\include
- C:\openssl_x64\include
Visual Studio にコピー&ペーストしてやると、こんな感じになりました。この状態でもう一度 nmake
してみてください。
コンパイルできた
初回の成功をしたときは、こんな感じのメッセージでした。
Visual Studio のソリューションエクスプローラーからは、(プロジェクトに追加していないので)コンパイルして生成したファイルは確認できません。Windows のエクスプローラーで表示してみると、目的のファイルが生成されていました。
- sqlcipher.dll
- sqlite3.c
sqlite3.c は Android 用のコンパイルにも再利用できます。コードの互換性を保つ意味でも重要かも。
SQLiteUnityKit で使うためには
sqlite3.dll から sqlcipher.dll に Assets を交換します。SqliteDatabase.cs
に DllImport
属性で関数を定義している部分があるので、libsqlcipher
から呼び出すように修正します。
前に libsqliteX
の .dll を使うパターンでポイントをメモした記事「Sqlitedatabase.cs の変更箇所」も参考になると思います。
// sqlite3_open を libsqlcipher.dll から呼び出す [DllImport("libsqlcipher", EntryPoint = "sqlite3_open")] // 他の関数も全部修正 // 以下の暗号化用の関数を新しく2つ追加する [DllImport("libsqlcipher", EntryPoint = "sqlite3_key")] private static extern int sqlite3_key(IntPtr stmHandle, string key, int len); [DllImport("libsqlcipher", EntryPoint = "sqlite3_rekey")] private static extern int sqlite3_rekey(IntPtr stmHandle, string key, int len);
これで x86/x64 用の libsqlcipher.dll を用意して Unity の Assets に追加・設定すれば OK でした。
暗号化に対応しているかチェックする要点
定義されている関数を DUMPBIN オプションでチェックします。
以下は、「sqlcipher.dll.dump」ファイルに DLL の内容を書き出しました。
dumpbin /exports sqlcipher.dll /OUT:sqlcipher.dll.dump
ファイルをメモ帳などで開いて、sqlite3_key
で検索します。
うまく DLL に目的の関数が追加されてそうですね。(通常の sqlite3.dll には「SQLite - List Of Functions」のように sqlite3_key が定義にありません)
使い方のポイント
暗号化のポイントは簡単です。
まとめると、以下のように sqlite3_open
を呼び出したあとは、最初に sqlite3_key
を呼び出してください。
初回の動作
- DB ファイルが存在しない状態で sqlite3_open
- sqlite3_key でパスワードを設定
- sqlite3_close で暗号化ファイルを生成
2回目以降の動作
- DB ファイルが存在する状態で sqlite3_open
- sqlite3_key でパスワードを設定
- SELECT 文などを実行する
- sqlite3_close で閉じる
public void Sample() { var path = pathDB; IntPtr stmHandle; if (sqlite3_open(path + "", out _connection) != SQLITE_OK) { throw new SqliteException("Could not open database file: " + path); } var result = sqlite3_key(_connection, "password", "password".Length); ExecuteQueryExec("BEGIN"); sqlite3_exec(_connection, "CREATE TABLE charactors ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, data1 INTEGER, data2 TEXT)", IntPtr.Zero, IntPtr.Zero, out stmHandle); sqlite3_exec(_connection, "INSERT INTO charactors (name, data1, data2) VALUES ('魔想志津香', 200, '火爆破')", IntPtr.Zero, IntPtr.Zero, out stmHandle); ExecuteQueryExec("COMMIT"); sqlite3_close(_connection); }
暗号化の注意点は、いまのところ暗号化したファイルを開くことができる DB ブラウザーがなさそうです。「SQLiteStudio」はできそうな気もするのですが、(いまのところ)うまく設定できないでいます。(できるなら教えてほしいです)
このあたりは以下が実例として参考になりそうです。
参考
- 作者:結城 浩
- 発売日: 2015/08/26
- メディア: 単行本
現代暗号入門 いかにして秘密は守られるのか (ブルーバックス)
- 作者:神永 正博
- 発売日: 2017/10/18
- メディア: 新書
WHY BLOCKCHAIN なぜ、ブロックチェーンなのか?
- 作者:坪井 大輔
- 発売日: 2019/07/12
- メディア: 単行本(ソフトカバー)