webentwicklung-frage-antwort-db.com.de

Android In-App-Abrechnung: Sichern des öffentlichen Schlüssels der Anwendung

Von der Android In App Billing Version 3 (TrivialDrive) -Beispielanwendung, die mit SDK geliefert wird

Hauptaktivität.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";

Ich bin mir nicht sicher, ob ich diese Sicherheitsmaßnahme verstehe. Ich weiß, wie Sie den öffentlichen Schlüssel der Anwendung (der bereits 64-Basencode codiert ist) von der Google Play Developer Console erhalten. 

Was ich nicht verstehe, ist dieser Teil

 /* 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
 */

Soweit ich weiß, handelt es sich bei diesem öffentlichen Schlüssel um eine konstante Zeichenfolge, die von Google während des Anwendungsuploadvorgangs angegeben wird. 

Wie können wir den gleichen Schlüssel programmgesteuert mit einem Bitbearbeitungsprozess erstellen? Hat das schon mal jemand gemacht? Gibt es einen Beispielcode dafür?

60
Krishnabhadra

Etwas wie das:

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

oder 

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

oder etwas, das den Schlüssel nicht in base64-Klartext in einer einzelnen Zeichenfolge einfügt. Wahrscheinlich wäre auch etwas, das den Schlüssel nicht in base64 speichert, eine gute Idee, da rohe base64-Textfragmente ziemlich leicht zu erkennen sind.

Es ist keine besonders gute Möglichkeit, den Schlüssel zu schützen. Es schützt jedoch vor einem trivialen Angriff, bei dem jemand in APK nach wörtlichen Zeichenketten sucht und nach etwas sucht, das wie ein base64-kodierter öffentlicher Schlüssel aussieht. Zumindest lässt man die # $ # $ er etwas arbeiten.

Vermutlich können böse Menschen schlechte Dinge tun, wenn sie Ihren öffentlichen Schlüssel identifizieren. Google scheint dies offenbar zu glauben. Ich kann mir vorstellen, was dieser Schritt bewirkt, aber ich bin mir nicht sicher, ob ich wirklich darüber in einem offenen Forum spekulieren möchte, und irgendjemandem irgendwelche Ideen geben möchte. Sie möchten es trotzdem tun.

Die grundlegende Plotzusammenfassung würde bedeuten, dass Sie es für jemanden schwieriger machen, eine Anwendung zu schreiben, die eine Anwendung programmgesteuert entwertet.

Man geht davon aus, dass jeder, der dies tut, davon lebt, 20 oder 30.000 Android-Apps zu knacken und sie erneut zu veröffentlichen. Die Chancen stehen gut, ich nehme an, dass sie keine weiteren zehn Minuten brauchen werden, um Ihre App zur Liste der 20.000 Android-Apps hinzuzufügen, die bereits von einem Programm beschädigt wurden, wenn sie tatsächlich etwas manuelle Arbeit leisten müssen. Es sei denn, Sie haben eine Top-Tier-Anwendung. Und dann ist der Kampf möglicherweise endlos und wahrscheinlich letztendlich vergeblich.

Das Aufteilen des Schlüssels in aufeinander folgende Blöcke (wie in einer anderen Antwort vorgeschlagen) ist wahrscheinlich nicht gut genug. Weil der Schlüssel in aufeinanderfolgenden Strings in den String-Konstantentabellen in der APK endet. Zu leicht, das mit einem Programm zu finden.

43
Robin Davies

Eine Alternative besteht darin, einige grundlegende Transformationen für den Schlüssel vorzunehmen.

// 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 );

Die Idee wäre also, Ihren ursprünglichen Schlüssel als base64EncodedPublicKey einzugeben und den obigen Code auszuführen. Er würde Klein- und Großbuchstaben austauschen und das Ergebnis in base64EncodedPublicKey zurücksetzen. Sie können das Ergebnis dann aus dem Debugger kopieren und als ursprünglichen base64EncodedPublicKey-Wert in den Code einfügen. An diesem Punkt wird Ihr Schlüssel umgewandelt (Groß- und Kleinschreibung geändert) und zur Laufzeit wird er wieder in das richtige Gehäuse eingefügt und funktioniert weiterhin.

Das Obige ist offensichtlich eine ziemlich grundlegende Transkodierung, aber Sie können kreativer sein, die Reihenfolge von A-Z umkehren, ungerade und gerade Zahlen vertauschen, Vokale gegen gerade Zahlen vertauschen. Das Problem hierbei ist, dass, wenn ich Code in das obige Snippet einsetze, das eine Reihe interessanter Transkodierungen durchführt und dann jeder kopiert und diesen in seine Projekte einfügt, ein Cracker die Transkodierung selbst leicht sehen und verwenden kann (vom Betrachten) dieser Beitrag)! Man muss sich also nur ein paar Transformationen einfallen lassen.

Ich habe die oben genannte Arbeit absichtlich in beide Richtungen vorgenommen (wenn Sie sie zweimal ausführen, erhalten Sie Ihren ursprünglichen Wert zurück), da es einfach ist, den Algorithmus auf Ihrem ursprünglichen Schlüssel auszuführen. Ich denke, es ist ziemlich nett, es sieht so aus, als würde der eigentliche Schlüssel als reiner Text dort sitzen, ein zufälliger Cracker könnte versuchen, das zu wechseln und dann verwirrt sein, wenn er nicht funktioniert.

13
Steven Craft

Sie können es so in Stücke teilen

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

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

Jede Art von Manipulationen reicht aus.

Sie können den öffentlichen Schlüssel nicht perfekt vor dem Angreifer verbergen. Sie müssen lediglich die Zeichenfolge manipulieren, um einen Angreifer ein wenig zu verwirren

Sie können einige Zeichenfolgen hinzufügen und entfernen, wenn es benötigt wird, oder es in Stücke teilen.

5
NaviRamyle

Was ich tat, war, den Schlüssel in ein Char-Array umzuwandeln, ihn in zwei Teile zu teilen und ihn dann bei Bedarf wie folgt neu aufzubauen:

@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

Führen Sie drei einfache Schritte aus, um den API/Secret-Schlüssel zu schützen

Wir können Gradle verwenden, um den API-Schlüssel oder den geheimen Schlüssel zu sichern. Überprüfen Sie meine Antwort .

0
SANAT

Aufbauend auf Steven Crafts Antwort mit Hilfe von gidds

Hier ist ein sauberer Code. Außerdem wird die Ziffer (0-9) gegen das ASCII-Zeichen (37-46) ausgetauscht und umgekehrt. Geschrieben in Kotlin.

 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

Verwenden Sie diese -> https://Edge-developer.github.io/BillingGenerator/ , um alle in einer Fliege zu generieren

0
Micklo_Nerd