42

Actually this is a little bit silly about protecting public key (what is the definition of public key then?) but as per the documentation by Google:

To keep your public key safe from malicious users and hackers, do not embed it in any code as a literal string. Instead, construct the string at runtime from pieces or use bit manipulation (for example, XOR with some other string) to hide the actual key. The key itself is not secret information, but you do not want to make it easy for a hacker or malicious user to replace the public key with another key.

Are there any recommended way to do it?

I know there are many ways to do it, I just don't want to follow the same way how people handle password hashing in the past (e.g. md5, sha1 etc), I want to know the best practice in the above use case.

4

5 に答える 5

38

これはこのあたりでよく出てきます:)引用している段落の背後にある考え方は、アプリ内課金を安全にするには、トランザクションの署名を確認する必要があるということです。これらは、開発者アカウントに関連付けられた秘密鍵で署名されています。キーはGoogleのサーバーにあるため、他の誰もそれを使用してデータに署名できないと想定するのはかなり安全です。それを確認するには、開発者コンソールからコピーできる公開鍵が必要です。誰かがあなたのアプリでそれを置き換えた場合、彼らはそれをだまして、許可されていないソースからのアプリ内請求トランザクションを受け入れる可能性があります。isLicensed()ただし、実際には、適切な場所でコードを変更して、、または同様のメソッドに対して常にtrueを返すようにする方がはるかに簡単でhasItem()あり、誰もこれを行いません。

もちろん、キーを保護する最善の方法は、アプリにキーをまったく含まないことです。すべてのトランザクション検証ロジックをサーバーに移動し、HTTPSを使用してサーバーに接続します。証明書チェーンを適切に検証して、自分のサーバーと通信していることを確認します。そうしないと、誰かがDNSをいじって、アプリをだまして自分のサーバーに接続する可能性があります。iOSの購入に対する同様の攻撃が数週間前に発表されました。

次善の策は、キーをなんとかして難読化し、アプリに含めることです。これにはサーバーが必要ないという利点がありますが、欠点は、誰かが十分に判断した場合、アプリのバイトコードをいつでも逆にすることができるため、サーバーを理解できることです。したがって、最善の策は、公開フォーラムに表示されない独自の方法を考え出すことです:)少し難しくするために、検証部分をネイティブコードで実装できますが、これは難しいです(ただし、そうではありません)。不可能)分析する。それでも、前述のように、適切な場所にバイトコードをパッチすることは、公開鍵を置き換えようとするよりもはるかに簡単であるため、ほとんどのクラッカーはそれを実行します。

于 2012-08-01T09:16:47.927 に答える
32

少なくとも単純なテキスト変換を実行します。単純なdexの逆アセンブルでは、公開鍵は公開されないという考え方です。

単純な文字列のエンコード/デコードを行う関数の例を次に示します。

/**
 * Simple String transformation by XOR-ing all characters by value.
 */
static String stringTransform(String s, int i) {
   char[] chars = s.toCharArray();
   for(int j = 0; j<chars.length; j++)
      chars[j] = (char)(chars[j] ^ i);
   return String.valueOf(chars);
}

次に、秘密鍵はエンコードされた文字列としてソースに保存され(この関数でエンコードされます)、実行時に同じ関数でデコードされます。これは、Googleが提案する一種の「XOR」方式です。

'i'パラメータは自分で作成します。0x27などのランダムなものなら何でも機能します。この方法でさらに文字列を非表示にする場合は、変換ごとに異なる「i」を使用します。

于 2012-07-30T06:05:10.607 に答える
11

キーを手動で難読化する代わりに、難読化ツールに自動的に難読化させることもできます。ProGuardはAndroidSDKの一部ですが、ほとんどの場合、文字列ではなく、クラス/フィールド/メソッド名をわかりにくくします。Android専用の兄弟であるDexGuardは、文字列暗号化、クラス暗号化、およびリフレクションを適用して、難読化のレイヤーをさらに追加できます。無料ではありませんが、時間を節約でき、手動で行うよりもおそらく効果的です。

(私はProGuardとDexGuardの開発者です)

于 2012-08-05T16:18:50.850 に答える
4

公開鍵をサーバー側に保存し、Google Playから応答を受け取ったら、鍵がその応答をサーバーに送信し、サーバーで操作を実行することを確認します。

于 2012-07-26T14:55:54.283 に答える
1

公開鍵はbase64でエンコードされている([a-zA-Z0-9+/])ので、@ PointerNullのソリューションの厄介な問題のように、難読化された文字列をエスケープする必要性を簡単に回避できます。

代わりに、最初に問題の文字を6ビット整数に変換することで難読化を実行できます。次に、ビット操作(XORなど)を実行してから、base64でエンコードされた文字に変換し直します。文字のエスケープは必要ありません。

于 2014-05-16T16:51:50.703 に答える