Androidから安全に独自のWebAPIを実行する [端末にパスワード保存]
今回はAndroidの端末にパスワード(秘密鍵など)を保存しますが、Javaコードだと「初心者」でも簡単に逆コンパイルが可能ですので解析されてしまいます。Javaコードを難読化する手法もありますが、ほぼ意味がないです。
NDKを使用してC++言語のコードで書いて「.so」の共有ファイルに保存する方法があります。ですが、逆アセンブルされたら危険です。
ただ、逆アセンブルで生成されたアセンブリ言語は「熟練者」の方ではないと解析が難しいです。例として113 KBの「.so」ファイルは約2万行のアセンブリ言語となります。 ※全て読む必要はないですが。
最終的にはC++で暗号化アルゴリズムを実装、パスワード(秘密鍵)を埋め込み、デバッグ時、証明書フィンガープリント(ハッシュ)などの対策を施す。SSL/TLS通信でWebAPIにアクセス。加えてGoogle Sign-In(サインイン)でOAuth認証(オーオース)を行う。
これならば「.so」ファイルを逆アセンブルされても、OAuth認証があるので勝手にWebAPIを操作する事は不可能に近いと思います。
LVLとOAuth認証の比較
Google Sign-Inの前にLVL(License Verification Library)も調査したけど、基本的に有料アプリが対象で、さらにサーバー側の連携がない模様です。
SSL/TLS
HttpURLConnectionではなくHttpsURLConnectionを使用する。
// HTTPS通信 URL myUrl = new URL("https://www.petitmonte.com/"); HttpsURLConnection connection = (HttpsURLConnection) myUrl.openConnection();
NDK
暗号化アルゴリズムはオープンソースを利用するか、独自で記述すると良い。DES/RC4/AESなどありますが、お好きなものを組み合わせると解析されにくいです。
パスワードのハードコーディングは避けて、配列にしたり組み合わせたりXORなどをしてあげると良いです。
Google Sign-In
Google Cloud Platformの「APIとサービス」の「認証情報」の「認証情報の作成」から「OAuthクライアントID」を選択します。Android側は「Android」(Android クライアント 1)で、サーバー側は「ウェブアプリケーション」(ウェブ クライアント 1)です。2つ必要なので注意して下さい。
Android側の「SHA-1 署名証明書フィンガープリント」は証明書フィンガープリント(MD5/SHA1/SHA-256)を確認するを参照。リリース版のAPKファイルがあればAndroidのAPKファイルを逆コンパイルするでも確認可能です。
サーバー側は「承認済みのJavaScript 生成元」「承認済みのリダイレクト URI」は未記入でOKです。
OAuth 同意画面でアイコンは登録しない方が良いです。Googleの対応に時間がかかりますのでご注意ください。途中で削除(キャンセル)できません。
Google Sign-In APIを使用する場合は「家族のポリシー要件の違反」 (Violation of Families Policy Requirements)に注意して下さい。13才未満に対してこのAPIは使用できません。必然的にアプリは13歳以上となります。
OAuth認証の流れはAndroid側ではaccount.getIdToken()で「IDトークン」を取得します。それをサーバー側で受け取って$payload = $client->verifyIdToken(IDトークン)で検証します。$payload['email']でメールアドレスも取得可能です。
コードの詳細はGoogle公式サイトや検索して見てください。
参考サイト
Google Sign-In を使ってサーバー側で認証を行う
Androidで安全にパスワードを保存する