sh1’s diary

プログラミング、読んだ本、資格試験、ゲームとか私を記録するところ

Unity SQLiteUnityKit 暗号化 SQLCipher (SQLite) を Android で利用する(.so コンパイル)

f:id:shikaku_sh:20200214142400p:plain:w350
SQLCipher

前回記事で Unity では、 Windows プラットフォーム向けの SQLCipher DLL ファイルの作り方と使い方を書きました。

今回は、Android 向けの SQLCipher の .so ファイルの作り方をメモした内容です。

環境構築

  • WSL (Windows subsystem for linux)
  • Unity 2019.3 に合わせて Android NDK (r19)
  • OpenSSL
  • sqlite3.c (前回記事で作成したものを再利用)

NDK のバージョンは Unity のバージョンにあわせる必要があります。「Unity Editor system requirements」などを参照します。

Windows で開発しているため、Android 向けの .so ファイルを作成したくても Windows では通常、適当なコンパイルが難しいです。そこで WSL 環境下の Linux で、コンパイルしました。

これだと、Windows ユーザーでも簡単です。

WSL の環境準備

つぎの記事のように、WSL で Ubuntu を立ち上げます。ちゃんと、起動して C ドライブ(/mnt/c/)を参照できれば OK でしょう。

f:id:shikaku_sh:20200214102229p:plain:w500

基本的な Linux コマンドの説明は省略します。

OpenSSL

WSL 環境下で OpenSSL を静的ライブラリー (.a) を作成します。初めてやってみるとけっこうむずかしいです。(やってみた例

Windows のときは、「Shining Light Prductions」から OpenSSL をインストールしたように今回も用意されたものでやろうと思います。ちょうど Android 向けに openssl を公開しているリポジトリーがあったので、これをクローンすることにします。

f:id:shikaku_sh:20200214190234p:plain:w500
Linux 環境の git は、ほんと手早くて便利

mkdir sqlite3
cd sqlite3
git clone https://github.com/KDAB/android_openssl.git

git のコマンドが走らないときは、パッケージをインストール、または、更新しよう。

あっという間に OpenSSL の準備が完了しました。

f:id:shikaku_sh:20200214190332p:plain:w400
OpenSSL のファイルは準備完了

sqlite3.c のコピー

SQLite3 の関数を定義した最もコアなソース sqlite3.c ファイルは、Windows で作成したものと同じものにしたいので、Windows 版で作成したものをコピーすることにします。

WSL は /mnt/c/ を通して C ドライブ直下にアクセスできるので、こんな感じになります。

 cp /mnt/c/repo/sqlcipher/sqlite3.c sqlite3.c

これで、ファイルの準備ができました。

sqlite3.c ファイルは x86/x64 で別々にコピーしたほうがよいと思います。(データを比べてないので、詳細を調べていません)

コンパイラー (NDK) の準備

Unity 2019.3 にあわせて NDK 19c をダウンロードして、圧縮ファイルを解凍します。

ファイルがかなりあるため、解凍するまで数分待ちます。

wget https://dl.google.com/android/repository/android-ndk-r19c-linux-x86_64.zip
unzip android-ndk-r19c-linux-x86_64.zip -d ndk

解凍完了すると、こんな感じになりました。

f:id:shikaku_sh:20200214190520p:plain:w400
進捗

補足として、NDK r19 からビルド(コンパイル)のやり方が変わっています。古い記事とやりかたを混同しないように注意が必要です。

コンパイル

NDK でコンパイルするための環境変数を定義していきます。

export ANDROID_NDK_HOME=$HOME/sqlite3/ndk/android-ndk-r19c
export LLVM_L_X86_64=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64
export TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64
export TOOLCHAIN_BIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin
export PATH=$TOOLCHAIN_BIN:$PATH
echo $PATH

結論としては、ビルドしやすいように PATH に NDK のツールチェインのパスを通してあげることです。

今度は、OpenSSL の環境変数も設定します。

export OPENSSL_STATIC_LIB=$HOME/sqlite3/android_openssl/static

今回のコンパイルでは、Android 28 を指定しています。(詳細は「Android version history」などを参考にします)

f:id:shikaku_sh:20200214190620p:plain:w500
コンパイル

# x64 のビルド
mkdir arm_x64
aarch64-linux-android28-clang -shared -DSQLITE_HAS_CODEC -fPIC -I ${OPENSSL_STATIC_LIB}/include sqlite3.c -o arm_x64/libsqlcipher.so ${OPENSSL_STATIC_LIB}/lib/libcrypto_arm64-v8a.a

# x86 のビルド
mkdir arm_x86
armv7a-linux-androideabi28-clang -shared -DSQLITE_HAS_CODEC -fPIC -I ${OPENSSL_STATIC_LIB}/include sqlite3.c -o arm_x86/libsqlcipher.so ${OPENSSL_STATIC_LIB}/lib/libcrypto_armeabi-v7a.a

sqlite3.c は x86/x64 で別々に用意する必要があるのかどうかは知らないです。Windows では別々に作れてるし、使い分けました。

完成しました。

f:id:shikaku_sh:20200214190658p:plain:w500
あっさり

暗号化に対応しているかチェックする要点

これも Windows の dumpbin と同じようにちゃんと sqlite3_key 関数が定義されたライブラリーかどうかをチェックしておきましょう。

cd arm_x86
/usr/bin/objdump --all-headers libsqlcipher.so > libsqlcipher.so.dump

cd arm_x64
/usr/bin/objdump --all-headers libsqlcipher.so > libsqlcipher.so.dump

f:id:shikaku_sh:20200214190748p:plain:w400
ただのテキストファイルです

x86/x64 かどうかのチェックは「補足」の記事を参考に。

問題なさそうですね。

f:id:shikaku_sh:20200214190830p:plain:w400
dump のチェック

これで、WindowsAndroid 向けの DllImport に対応したライブラリーファイル (x86/x64) を用意することができました。

おまけ

参考にした記事にも書かれていることですが、ビルドしたファイルは、ライブラリーのファイルサイズを削減できていることや、JAVA などの依存も消えてシンプルにスマートになりました。

SQLiteUnityKit を基礎にして、自分なりに DB 用クラスをカスタマイズできるのもメリットですが、個人的には、こうした試行錯誤を1回経験しておくというのもよかったと思います。広い経験値があります。(純血の Windows ユーザーなら特にそう思う)

こうして結果だけ書くとシンプルなコンパイルの工程だけど、試行錯誤にけっこうな時間がかかるやつでした。

デバッグ

むずかしくてうまくコンパイルできない、どうしてだ! ってなったときは、とりあえず SQLite3 だけのコンパイルが NDK でやれるのかチェックしてみるとよいと思います。

f:id:shikaku_sh:20200214190914p:plain:w500
「amalgamation」のとおり、アマルガムな用途のファイルです

mkdir sqlite-test
cd sqlite-test
wget https://www.sqlite.org/2020/sqlite-amalgamation-3310100.zip
unzip sqlite-amalgamation-3310100.zip

cd sqlite-amalgamation-3310100
mkdir arm_x86
mkdir arm_x64
armv7a-linux-androideabi28-clang -shared sqlite3.c -fPIC -o arm_x86/sqlite3.so
aarch64-linux-android28-clang -shared sqlite3.c -o arm_x64/sqlite3.so

環境変数export で、ちゃんとパスを定義できているか見てみるのも大切。(ウィンドウをあたらしくすると export 環境変数も消える)

env
echo $PATH

補足として、sqlite3.c のファイルはここにそもそもあるじゃないか! と思って、これを代用しても SQLCipher のコンパイルは通ります。通りますが、sqlite3_key の関数定義は追加されません。この sqlite3.c には定義されていないからですね。

参考

暗号技術入門 第3版

暗号技術入門 第3版

  • 作者:結城 浩
  • 発売日: 2015/08/26
  • メディア: 単行本

新版暗号技術入門 秘密の国のアリス

新版暗号技術入門 秘密の国のアリス

暗号理論入門 原書第3版

暗号理論入門 原書第3版

  • 発売日: 2012/04/20
  • メディア: 単行本