web-dev-qa-db-ja.com

Android In App Billing:アプリケーション公開鍵の保護

From Android In App Billingバージョン3(TrivialDrive)でSDKに付属するサンプルアプリケーション

MainActivity.Java

/* base64EncodedPublicKey should be YOUR APPLICATION'S PUBLIC KEY
 * (that you got from the Google Play developer console). This is not your
 * developer public key, it's the *app-specific* public key.
 *
 * Instead of just storing the entire literal string here embedded in the
 * program,  construct the key 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 we don't
 * want to make it easy for an attacker to replace the public key with one
 * of their own and then fake messages from the server.
 */
String base64EncodedPublicKey = "CONSTRUCT_YOUR_KEY_AND_PLACE_IT_HERE";

さて、このセキュリティ対策を理解しているかどうかはわかりません。 Google Play開発者コンソールからアプリケーションの公開キー(既にBase 64エンコードされている)を取得する方法を知っています。

私が理解していないのはこの部分です

 /* Instead of just storing the entire literal string here embedded in the
 * program,  construct the key at runtime from pieces or
 * use bit manipulation (for example, XOR with some other string) to hide
 * the actual key
 */

私の知る限り、この公開鍵は定数文字列であり、アプリケーションのアップロードプロセス中にGoogleから提供されます。

ビット操作プロセスを使用してプログラムで同じキーを作成するにはどうすればよいですか?誰かが前にそれをやったことがありますか?これを行う方法に関するサンプルコードはありますか?

61
Krishnabhadra

このようなもの:

String Base64EncodedPublicKey key = "Ak3jfkd" + GetMiddleBit() + "D349824";

または

String Base64EncodedPublicKey key = 
         DecrementEachletter("Bl4kgle") + GetMiddleBit() + ReverseString("D349824");

または、単一の文字列でキーをbase64平文に入れないもの。おそらく、生のbase64テキストフラグメントを見つけるのは非常に簡単なので、キーをbase64に保存しないものもお勧めです。

キーを保護するのに特に良い方法ではありません。しかし、だれかがAPKのリテラル文字列を検索してbase64でエンコードされた公開キーのように見えるものを探すというささいな攻撃から保護します。少なくとも、#$ $ ersを少し動作させます。

おそらく悪人はあなたの公開鍵を特定すれば悪いことをすることができます。どうやらGoogleはそう考えているようだ。このステップが何をするかは推測できますが、オープンフォーラムでそのことを推測し、誰かにアイデアを出したいとは思いません。あなたもそれをやりたい。

基本的なプロットの要約は、誰かがプログラムでアプリケーションのLVLを解除するア​​プリケーションを作成するのをより難しくしているということです。

これを行っている人はだれでも20から30,000のクラッキングを行っていると仮定しますAndroidアプリとそれらを再公開します。 20,000のリストへAndroidプログラムによって既に壊れているアプリ。実際に少しの手作業を行わなければならない場合。トップレベルのアプリがない限り。潜在的に無限であり、おそらく最終的には無駄です。

(別の回答で提案されているように)キーを連続したチャンクに分割するだけでは、おそらく十分ではありません。キーはAPKの文字列定数テーブルの連続した文字列になるためです。プログラムで簡単に見つけることができます。

43
Robin Davies

別の方法は、キーに対していくつかの基本的な変換を行うことです。

// Replace this with your encoded key.
String base64EncodedPublicKey = "";

// Get byte sequence to play with.
byte[] bytes = base64EncodedPublicKey.getBytes();

// Swap upper and lower case letters.
for (int i = 0; i < bytes.length; i++) {
    if(bytes[i] >= 'A' && bytes[i] <= 'Z')
        bytes[i] = (byte)( 'a' + (bytes[i] - 'A'));
    else if(bytes[i] >= 'a' && bytes[i] <= 'z')
        bytes[i] = (byte)( 'A' + (bytes[i] - 'a'));
}

// Assign back to string.
base64EncodedPublicKey = new String( bytes );

したがって、アイデアは元のキーをbase64EncodedPublicKeyとして入れて上記のコードを実行し、小文字と大文字を入れ替えて結果をbase64EncodedPublicKeyに戻すというものです。その後、デバッガから結果をコピーし、元のbase64EncodedPublicKey値としてコードに貼り付けることができます。この時点で、キーは変換され(大文字と小文字が切り替えられます)、実行時に正しい大文字に戻され、動作を継続します。

上記は明らかに基本的なトランスコードですが、より創造的であり、A-Zの順序を逆にしたり、奇数と偶数を入れ替えたり、母音を偶数に入れ替えたりすることができます。ここでの問題は、上記のスニペットにコードを入れてより多くの興味深いトランスコードを実行し、それを誰もがコピーしてプロジェクトに貼り付けると、クラッカーはトランスコードを簡単に確認して使用できることですこの郵便受け)!したがって、あなたは自分でいくつかの変換を考え出す必要があります。

元のキーでアルゴリズムを簡単に実行できるようにするため、上記の作業を両方向で意図的に行いました(2回実行すると元の値が返されます)。本物のキーがプレーンテキストとしてそこに座っているように見えるのはちょっときちんとしたものだと思います、カジュアルなクラッカーはこれを切り替えて、うまくいかないときに混乱するかもしれません。

13
Steven Craft

このように分割できます

String piece1 = "SDFGJKGB4UIH234WE/FRT23RSDF/3DFUISDFVWE";
String piece2 = "SDFGJKGB4UIHUISDFVWE";
String piece3 = "BDYASGBDNAWGRET24IYE23das4saGBENWKD";
String piece4 = "432423SDF23R/+SDDS";

mHelper = new IabHelper(this, piece1 + piece2 + piece3 + piece4);

あらゆる種類の操作が行われます。

公開鍵を攻撃者から完全に隠すことはできません。攻撃者を少し混乱させるために文字列を操作するだけです

必要に応じて文字列を追加して削除したり、チャンクに分割したりできます。

5
NaviRamyle

私がやったことは、キーをchar配列に変換し、2つに分割し、必要に応じて次のように再構築することでした:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_shop);

    char[] base64KeyByteArray = ArrayUtils.addAll(getPublicKeyChunk1(), getPublicKeyChunk2());

    Log.d(TAG, String.valueOf(base64KeyByteArray));
}

private char[] getPublicKeyChunk1() {
    return new char[]{82, 73, 67, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107,
            105, 71, 57, 119, 79, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73,
            73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 121, 55, 81, 76, 122, 67, 105, 80, 65,
            110, 105, 101, 72, 66, 53, 57};
}

private char[] getPublicKeyChunk2() {
    return new char[]{82, 43, 68, 47, 79, 121, 122, 110, 85, 67, 118, 89, 108, 120, 43, 49,
            80, 100, 67, 108, 55, 90, 57, 103, 119, 57, 87, 78, 79, 111, 53, 101, 80, 71,
            117, 74, 104, 82, 87, 97, 100};
}
2
Adrian

Steven Craft's Answer の構築 gidds から得た助けを借りて

ここにきれいなコードがあります。さらに、ASCII文字(37〜46)と数字(0〜9)を入れ替えます。コトリンで書かれました。

 val string = "Hello World 012345679 %&()"
 fun String.swapCase() = map {
        when {
            it.isUpperCase() -> it.toLowerCase()
            it.isLowerCase() -> it.toUpperCase()
            it.isDigit() -> (37 + (it.toInt() - 48)).toChar()
            it.isDefined() -> if (it.toInt() >= 37 && it.toInt() <= 46) (48 + (it.toInt() - 37)).toChar() else it
            else -> it
        }
    }.joinToString("")
    println(string.swapCase()) // hELLO wORLD %&'()*+,. 0134

この-> https://Edge-developer.github.io/BillingGenerator/ を使用して、それらすべてを即座に生成します。

1
EdgeDev

3つの簡単な手順に従ってAPI /秘密鍵を保護します

Gradleを使用して、APIキーまたは秘密キーを保護できます。 answer を確認してください。

0
SANAT