[解決済み] アプリケーションにおけるプライベートAPIキーの保存と保護に関するベストプラクティス [終了しました]。
質問
ほとんどのアプリ開発者は、アプリにいくつかのサードパーティライブラリを統合しています。DropboxやYouTubeなどのサービスにアクセスするため、あるいはクラッシュのログを取るためであれば。サードパーティのライブラリやサービスの数は、驚異的な数にのぼります。それらのライブラリやサービスのほとんどは、何らかの方法でサービスと認証することで統合されます。ほとんどの場合、これはAPIキーによって行われます。セキュリティのために、サービスは通常、公開鍵と秘密鍵(しばしば秘密鍵とも呼ばれる)を生成する。残念ながら、サービスに接続するためには、この秘密鍵を認証に使用する必要があり、したがって、おそらくアプリケーションの一部となります。 言うまでもなく、これはセキュリティ上、非常に大きな問題に直面しています。公開鍵と秘密鍵は、APKから数分で抽出でき、簡単に自動化することができます。
このようなものがあったとして、秘密鍵をどのように保護すればよいのでしょうか。
public class DropboxService {
private final static String APP_KEY = "jk433g34hg3";
private final static String APP_SECRET = "987dwdqwdqw90";
private final static AccessType ACCESS_TYPE = AccessType.DROPBOX;
// SOME MORE CODE HERE
}
秘密鍵を保管するための最も安全で最善の方法は何だと思いますか?難読化、暗号化、あなたはどう思いますか?
解決方法は?
-
そのままでは、コンパイルされたアプリケーションには、キー文字列だけでなく、APP_KEYとAPP_SECRETという定数名も含まれています。このような自己文書化されたコードからキーを抽出することは、例えばAndroidの標準ツールであるdxを使えば、非常に簡単です。
-
ProGuardを適用することができます。キー文字列はそのままで、定数名を削除します。また、クラスやメソッドの名前を、可能な限り意味のない短い名前に変更します。キーを取り出すには、どの文字列がどのような用途に使われるかを把握するために、もう少し時間がかかります。
ProGuardの設定は、あなたが恐れているほど難しくはないはずです。まず最初に、project.propertiesに書かれているように、ProGuardを有効にするだけでいいのです。サードパーティライブラリに問題がある場合、proguard-project.txt でいくつかの警告を抑制したり、難読化しないようにする必要があるかもしれません。例えば
-dontwarn com.dropbox.** -keep class com.dropbox.** { *; }
これはブルートフォースアプローチです。処理されたアプリケーションが動作するようになったら、このような設定を改良することができます。
-
例えばBase64エンコーディングや、できればもっと複雑なもの(ネイティブコードでもよい)を使って、コード内で文字列を手動で難読化することができます。ハッカーは、あなたのエンコードを静的にリバースエンジニアリングするか、適切な場所でデコードを動的に傍受する必要があります。
-
ProGuard の特殊な兄弟製品である、市販の難読化剤を適用することができます。 デックスガード . さらに、文字列とクラスを暗号化/難読化することができます。鍵の抽出には、さらに多くの時間と専門知識が必要です。
-
アプリケーションの一部を自分のサーバーで動作させることができるかもしれません。そこにキーを置いておけば、安全です。
鍵がどれだけ重要か、どれだけの時間やソフトウェアに余裕があるか、鍵に興味を持つハッカーはどれだけ洗練されているか、彼らはどれだけの時間を費やしたいか、鍵がハッキングされるまでの遅れはどれだけの価値があるか、成功したハッカーはどの程度の規模で鍵を配布するか、などです。鍵のような小さな情報は、アプリケーション全体よりも保護するのが難しい。本質的に、クライアントサイドで破られないものはありませんが、ハードルを上げることは可能です。
(ProGuardとDexGuardの開発者です。)
関連
-
Gradle のエラーです。gradle-core.jar (com.android.tools.build:gradle-core:x.x.x) を見つけられませんでした。
-
Android Studio を 3.6.3 にアップデートした後、構成 :classpath のアーティファクトをすべて解決できない。
-
アンドロイドスタジオのエラーを解決する --> Error:(1, 0) id 'com.android.application' を持つプラグインが見つかりません。
-
telnet'が内部コマンドまたは外部コマンドとして認識されない 解決方法
-
アンドロイドのエリプサイズを使用する
-
Android ProgressBarの色を変更する
-
AndroidでListViewを使ってカスタムテーブルを描画する
-
[解決済み] 新しいAPIキーを生成するための最適な方法は何ですか?
-
[解決済み] 新しいAndroid Fragmentをインスタンス化するためのベストプラクティス
-
[解決済み] APIキーとシークレットキーはどのように機能するのですか?APIキーやシークレットキーを他のアプリケーションに渡すのは安全ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
AAPT2エラーについて:詳しくはログをご確認ください。
-
adb devices OffLine Solution(オフラインソリューション
-
Android端末にADBが接続できない!を解決。理由: デバイスが認証されていない!
-
armeabi-v7a armeabi arm64-v8a パラメータの意味説明
-
aapt2エラー:ログを確認する(具体的な原因の探り方)
-
AndroidがMainActivityが包含クラスでないというエラーを報告する
-
Androidで発生した問題、解決策とヒント
-
android:EMSのプロパティ
-
ConstraintLayoutのいくつかのプロパティの概要(RelativeLayoutの強化版、LinearLayoutの比例プロパティを含む、階層ツールの削減)。
-
android.content.ActivityNotFoundException を解決します。Intent問題を処理するActivityが見つからない