アプリとデータに関するはなし


アプリとそこで利用するデータが別々になっていて、アプリは一つでデータを入れ替えるようなシステムがある。
データはユーザーに勝手に取り出されたくない。

という状態で、どういう設計をすればよいか?という話です。

なお、はじめに書いときますけどだいぶあたまわるい文章です。

方法1 データは暗号化して保存して、利用時に復号ファイルを作成する

アプリの開始時やファイル利用時等に一時的に復号ファイルを作成する。利用が終わったら削除する。

メリット

  • ファイルを利用する箇所のプログラムは復号ファイルを処理するため、暗号化対応をしなくて良い(暗号化に対応していないライブラリを利用できる)。
  • 実装が簡単(=コストが安い)。

デメリット

  • 復号ファイルが完全な状態で存在する期間中に復号ファイルを奪われるリスクがある。アプリが強制終了した場合などは削除処理が意図したとおりに実行されない可能性があるし、どんなに復号ファイルの生存期間を短くしようとしても復号ファイルを利用している間に復号ファイルを奪われることに対処するのは難しい。
  • 一時的に暗号化ファイルと復号ファイル二個が存在することになるので、容量の大きなファイルを扱う時はストレージの空き容量に注意が必要。
  • 容量の大きなファイルを復号するのはそれなりに時間がかかる。

方法2 データは暗号化して保存して、復号しながら処理する

復号ファイルを作成せず、暗号化ファイルを直接読み取りながら処理をする方法。

メリット

  • 復号ファイルが作られないので、ユーザーが奪おうと思っても奪いづらい。
  • 一時的に復号ファイルを作る分の余計なストレージ容量が必要ない。

デメリット

  • 復号処理をしながらデータを処理することになるので追加のCPU処理コストがかかる。
  • 復号処理を挟めないと実装できない(URLを渡すだけであとはいい感じに処理してくれるようなライブラリの場合、ソースがいじれないと使えない)。

方法3 データはユーザーからアクセスできない場所に置く

ファイルの暗号化を行わず、ユーザーがアクセスできない場所にファイルを置いておく。

メリット

  • 復号処理について考えなくて良い。
  • 実装が簡単。

デメリット

  • ユーザーがアクセスできない場所というのはすなわち自分もアクセスできない場所なので、そこにどうやってファイルを配置するか?(自分が容易にアクセスできる方法を用意してしまうと、そこが抜け穴になる可能性がある)。
  • 万が一のためのことを考えて暗号化しておいた方がよいかもしれないが、そうすると今度はいつ復号する?ふりだしに戻る。

ちなみに今のところ何も考えずに「暗号化」と書いているけど、暗号化・復号化をするためには鍵が必要になる。その鍵をどうやってアプリ内で取得するか?というのもまた結構たいへんな問題です。

まず、鍵は暗号化することができません。なぜなら鍵を復号するためにまた別の鍵が必要になるからです。その鍵はどうやって保存する?無限ループ…

方法1 アプリ内に鍵を持つ

アプリの中にどうにかして鍵を入れます。

メリット

  • 実装が簡単(=コストが安い)。

デメリット

  • アプリを解析されると鍵がバレる可能性がある。パッと見わからないようにある程度難読化する手段はいろいろ考えられるが、攻撃者が本気で解析しようとしたときに鍵がバレない保証はない。DVDやブルーレイの暗号化もこれで破られました…

方法2 アプリ内に鍵は持たず、どうにかして取得する

鍵はアプリ内にいれず、必要なときにサーバーから取得するなどしてどうにか入手します。
もちろん、入手した鍵はユーザーがアクセスできないプライベートな場所に保存する必要があります。

メリット

  • アプリを解析されても鍵はバレない。

デメリット

  • サーバーが必要。
  • サーバーへ鍵を取得しに行く部分がきちんと作られていないと、通信内容を傍受して鍵を取得したりできてしまう…
  • 取得した鍵を保存するところでうっかりミスると鍵がバレてしまう。

方法3 鍵は毎回違うものを使う

アプリ内に固定の鍵を持たず、サーバーから取得する鍵も毎回違うものを使う。

メリット

  • あんしん!

デメリット

  • 鍵が変わるということは暗号化データも変わる。ということは鍵が新しくなるごとに暗号化データも入れ替えなければいけない。事前ダウンロード型のシステムとは相性が悪い。
  • というわけでサーバー利用必須。
  • サーバーでの処理負荷もそれなりに大きい(暗号化したりするし)ので、運用コスト結構かかる。

いやー、安全安心なシステムを作るのって大変ですね!!