Die meisten App-Entwickler werden einige Bibliotheken von Drittanbietern in ihre Apps integrieren. Wenn Sie auf einen Dienst wie Dropbox oder YouTube zugreifen oder Abstürze protokollieren möchten. Die Anzahl der Bibliotheken und Dienste von Drittanbietern ist erschütternd. Die meisten dieser Bibliotheken und Dienste werden durch Authentifizierung beim Dienst integriert. Meistens geschieht dies über einen API-Schlüssel. Aus Sicherheitsgründen generieren Dienste normalerweise einen öffentlichen und privaten Schlüssel, der oft auch als geheimer Schlüssel bezeichnet wird. Leider muss dieser private Schlüssel zur Authentifizierung verwendet werden, um eine Verbindung zu den Diensten herzustellen, und daher wahrscheinlich Teil der Anwendung sein. Es ist unnötig zu erwähnen, dass dies mit einem immensen Sicherheitsproblem konfrontiert ist. Öffentliche und private API-Schlüssel können in wenigen Minuten aus APKs extrahiert und einfach automatisiert werden.
Angenommen, ich habe etwas Ähnliches, wie kann ich den geheimen Schlüssel schützen:
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
}
Was ist Ihrer Meinung nach die beste und sicherste Art, den privaten Schlüssel zu speichern? Verschleierung, Verschlüsselung, was denkst du?
quelle
Antworten:
So wie es ist, enthält Ihre kompilierte Anwendung die Schlüsselzeichenfolgen, aber auch die Konstantennamen APP_KEY und APP_SECRET. Das Extrahieren von Schlüsseln aus einem solchen selbstdokumentierenden Code ist beispielsweise mit dem Standard-Android-Tool dx trivial.
Sie können ProGuard anwenden. Die Tastenketten bleiben unberührt, die konstanten Namen werden jedoch entfernt. Wo immer möglich, werden auch Klassen und Methoden mit kurzen, bedeutungslosen Namen umbenannt. Das Extrahieren der Schlüssel dauert dann etwas länger, um herauszufinden, welche Zeichenfolge welchem Zweck dient.
Beachten Sie, dass das Einrichten von ProGuard nicht so schwierig sein sollte, wie Sie befürchten. Zunächst müssen Sie nur ProGuard aktivieren, wie in project.properties dokumentiert. Wenn es Probleme mit Bibliotheken von Drittanbietern gibt, müssen Sie möglicherweise einige Warnungen in proguard-project.txt unterdrücken und / oder verhindern, dass sie verschleiert werden. Zum Beispiel:
Dies ist ein Brute-Force-Ansatz. Sie können diese Konfiguration verfeinern, sobald die verarbeitete Anwendung funktioniert.
Sie können die Zeichenfolgen in Ihrem Code manuell verschleiern, z. B. mit einer Base64-Codierung oder vorzugsweise mit etwas Komplizierterem. vielleicht sogar nativer Code. Ein Hacker muss dann Ihre Codierung statisch rückentwickeln oder die Decodierung dynamisch an der richtigen Stelle abfangen.
Sie können einen kommerziellen Verschleierer wie ProGuards spezialisiertes Geschwister DexGuard anwenden . Es kann zusätzlich die Zeichenfolgen und Klassen für Sie verschlüsseln / verschleiern. Das Extrahieren der Schlüssel erfordert dann noch mehr Zeit und Fachwissen.
Möglicherweise können Sie Teile Ihrer Anwendung auf Ihrem eigenen Server ausführen. Wenn Sie die Schlüssel dort aufbewahren können, sind sie sicher.
Am Ende ist es ein wirtschaftlicher Kompromiss, den Sie eingehen müssen: Wie wichtig sind die Schlüssel, wie viel Zeit oder Software können Sie sich leisten, wie hoch entwickelt sind die Hacker, die sich für die Schlüssel interessieren, wie viel Zeit werden sie wollen Geben Sie aus, wie viel Wert eine Verzögerung ist, bevor die Schlüssel gehackt werden, in welchem Umfang erfolgreiche Hacker die Schlüssel verteilen usw. Kleine Informationen wie Schlüssel sind schwieriger zu schützen als ganze Anwendungen. Eigentlich ist nichts auf der Client-Seite unzerbrechlich, aber Sie können die Messlatte sicherlich höher legen.
(Ich bin der Entwickler von ProGuard und DexGuard)
quelle
Einige Ideen, meiner Meinung nach gibt nur die erste eine Garantie:
Bewahren Sie Ihre Geheimnisse auf einem Server im Internet auf, und greifen Sie sie bei Bedarf einfach zu und verwenden Sie sie. Wenn der Benutzer Dropbox verwenden möchte, hindert Sie nichts daran, eine Anfrage an Ihre Site zu richten und Ihren geheimen Schlüssel zu erhalten.
Legen Sie Ihre Geheimnisse in jni-Code, fügen Sie variablen Code hinzu, um Ihre Bibliotheken größer und schwieriger zu dekompilieren. Sie können die Tastenfolge auch in einige Teile teilen und an verschiedenen Stellen aufbewahren.
Verwenden Sie den Obfuscator, geben Sie auch das Code-Hash-Geheimnis ein und lösen Sie es später bei Bedarf.
Fügen Sie Ihren geheimen Schlüssel als letzte Pixel eines Ihrer Bilder in Assets ein. Lesen Sie es dann bei Bedarf in Ihrem Code. Das Verschleiern Ihres Codes sollte helfen, Code zu verbergen, der ihn liest.
Wenn Sie einen kurzen Blick darauf werfen möchten, wie einfach es ist, Ihren Apk-Code zu lesen, greifen Sie zu APKAnalyser:
http://developer.sonymobile.com/knowledge-base/tool-guides/analyse-your-apks-with-apkanalyser/
quelle
Ein anderer Ansatz ist, das Geheimnis überhaupt nicht auf dem Gerät zu haben! Siehe Mobile API-Sicherheitstechniken (insbesondere Teil 3).
Teilen Sie das Geheimnis zwischen Ihrem API-Endpunkt und einem App-Authentifizierungsdienst, indem Sie die altehrwürdige Tradition der Indirektion nutzen.
Wenn Ihr Client einen API-Aufruf tätigen möchte , fordert er den App-Authentifizierungsdienst auf, ihn zu authentifizieren (unter Verwendung starker Remote-Attestierungstechniken), und er erhält ein zeitlich begrenztes (normalerweise JWT ) Token, das vom Geheimnis signiert wird.
Das Token wird bei jedem API-Aufruf gesendet, bei dem der Endpunkt seine Signatur überprüfen kann, bevor er auf die Anforderung reagiert.
Das eigentliche Geheimnis ist auf dem Gerät niemals vorhanden. Tatsächlich hat die App keine Ahnung, ob sie gültig ist oder nicht. Sie fordert nur die Authentifizierung an und gibt das resultierende Token weiter. Wenn Sie das Geheimnis ändern möchten, können Sie dies als Vorteil der Indirektion tun, ohne dass Benutzer ihre installierten Apps aktualisieren müssen.
Wenn Sie also Ihr Geheimnis schützen möchten, ist es ein guter Weg, es nicht in Ihrer App zu haben.
quelle
Alter ungesicherter Weg:
Befolgen Sie 3 einfache Schritte, um die API / den geheimen Schlüssel zu sichern ( alte Antwort )
Wir können Gradle verwenden, um den API-Schlüssel oder den geheimen Schlüssel zu sichern.
1. gradle.properties (Projekteigenschaften): Variable mit Schlüssel erstellen.
2. build.gradle (Modul: App): Legen Sie die Variable in build.gradle fest, um in Aktivität oder Fragment darauf zuzugreifen. Fügen Sie den folgenden Code zu buildTypes {} hinzu.
3. Greifen Sie in Aktivität / Fragment mit der BuildConfig der App darauf zu:
Update:
Die obige Lösung ist im Open Source-Projekt hilfreich, um ein Commit über Git durchzuführen. (Danke an David Rawson und Riyaz-Ali für Ihren Kommentar).
Laut den Kommentaren von Matthew und Pablo Cegarra ist der oben beschriebene Weg nicht sicher und Decompiler ermöglicht es jemandem, die BuildConfig mit unseren geheimen Schlüsseln anzuzeigen.
Lösung:
Wir können NDK verwenden, um API-Schlüssel zu sichern. Wir können Schlüssel in der nativen C / C ++ - Klasse speichern und in unseren Java-Klassen darauf zugreifen.
Bitte folgen Sie diesem Blog, um API-Schlüssel mit NDK zu sichern.
Ein Follow-up zum sicheren Speichern von Token in Android
quelle
gradle.properties
sollte nicht in Git eingecheckt werden, so ist dies eine Möglichkeit, das Geheimnis zumindest aus festgeschriebenem Quellcode herauszuhaltenapk
(er wird der generiertenBuildConfig
Datei hinzugefügt ), obwohl dies definitiv eine gute Idee ist, verschiedene API-Schlüssel zu verwalten (z. B. in einem Open Source-Projekt)BuildConfig.java
Datei enthält den Schlüssel im Klartext. Dies ist nicht besser als das, was das OP bereits tut.Für diese Jungs wird es sich nicht verstecken, sperren Sie entweder
ProGuard
den Code. Es ist ein Refactor und einige bezahlte Verschleierer fügen einige bitweise Operatoren ein, um denjk433g34hg3
String zurückzugewinnen. Sie können das Hacken um 5 bis 15 Minuten verlängern, wenn Sie 3 Tage arbeiten :)Der beste Weg ist, es so zu lassen, wie es ist, imho.
Selbst wenn Sie auf der Serverseite (Ihrem PC) speichern, kann der Schlüssel gehackt und ausgedruckt werden. Vielleicht dauert das am längsten? Jedenfalls ist es im besten Fall eine Frage von wenigen Minuten oder ein paar Stunden.
Ein normaler Benutzer wird Ihren Code nicht dekompilieren.
quelle
Eine mögliche Lösung besteht darin, die Daten in Ihrer App zu codieren und zur Laufzeit zu dekodieren (wenn Sie diese Daten verwenden möchten). Ich empfehle außerdem, progaurd zu verwenden, um das Lesen und Verstehen des dekompilierten Quellcodes Ihrer App zu erschweren. Zum Beispiel habe ich einen verschlüsselten Schlüssel in die App eingefügt und dann eine Dekodierungsmethode in meiner App verwendet, um meine geheimen Schlüssel zur Laufzeit zu entschlüsseln:
Der dekompilierte Quellcode einer bewachten App lautet wie folgt:
Zumindest ist es mir kompliziert genug. So mache ich das, wenn ich keine andere Wahl habe, als einen Wert in meiner Anwendung zu speichern. Natürlich wissen wir alle, dass es nicht der beste Weg ist, aber es funktioniert für mich.
Dekompilierte Version:
und Sie können so viele Verschlüsselungsklassen mit einer kleinen Suche in Google finden.
quelle
Zum Hinzufügen zur @ Manohar Reddy-Lösung können Firebase-Datenbank oder Firebase RemoteConfig (mit dem Standardwert Null) verwendet werden:
Was ist bei dieser Lösung anders?
quelle
Dieses Beispiel hat verschiedene Aspekte. Ich werde einige Punkte erwähnen, von denen ich glaube, dass sie an keiner anderen Stelle ausdrücklich behandelt wurden.
Das Geheimnis auf der Durchreise schützen
Als Erstes müssen Sie für den Zugriff auf die Dropbox-API mithilfe des App-Authentifizierungsmechanismus Ihren Schlüssel und Ihr Geheimnis übertragen. Die Verbindung ist HTTPS, was bedeutet, dass Sie den Datenverkehr nicht abfangen können, ohne das TLS-Zertifikat zu kennen. Dies soll verhindern, dass eine Person die Pakete auf ihrer Reise vom mobilen Gerät zum Server abfängt und liest. Für normale Benutzer ist dies eine sehr gute Möglichkeit, die Privatsphäre ihres Datenverkehrs zu gewährleisten.
Was es nicht gut kann, ist zu verhindern, dass eine böswillige Person die App herunterlädt und den Datenverkehr überprüft. Es ist wirklich einfach, einen Man-in-the-Middle-Proxy für den gesamten Datenverkehr in und aus einem mobilen Gerät zu verwenden. Aufgrund der Art der Dropbox-API wäre in diesem Fall keine Demontage oder Rückentwicklung des Codes erforderlich, um den App-Schlüssel und das Geheimnis zu extrahieren.
Sie können eine Fixierung durchführen, bei der überprüft wird, ob das vom Server erhaltene TLS-Zertifikat das erwartete ist. Dies fügt dem Client eine Prüfung hinzu und erschwert das Abfangen des Datenverkehrs. Dies würde es schwieriger machen, den Verkehr im Flug zu inspizieren, aber die Pinning-Prüfung findet im Client statt, sodass es wahrscheinlich immer noch möglich wäre, den Pinning-Test zu deaktivieren. Es macht es allerdings schwieriger.
Das Geheimnis in Ruhe schützen
In einem ersten Schritt hilft die Verwendung von Proguard dabei, weniger deutlich zu machen, wo Geheimnisse verborgen sind. Sie können das NDK auch verwenden, um den Schlüssel und das Geheimnis zu speichern und Anfragen direkt zu senden, wodurch die Anzahl der Personen mit den entsprechenden Fähigkeiten zum Extrahieren der Informationen erheblich reduziert wird. Eine weitere Verschleierung kann erreicht werden, indem die Werte nicht für längere Zeit direkt im Speicher gespeichert werden. Sie können sie verschlüsseln und unmittelbar vor der Verwendung entschlüsseln, wie in einer anderen Antwort vorgeschlagen.
Erweiterte Optionen
Wenn Sie jetzt paranoid sind, das Geheimnis irgendwo in Ihrer App zu platzieren, und Zeit und Geld haben, um in umfassendere Lösungen zu investieren, können Sie die Anmeldeinformationen auf Ihren Servern speichern (vorausgesetzt, Sie haben welche). Dies würde die Latenz aller Aufrufe der API erhöhen, da diese über Ihren Server kommunizieren muss, und könnte die Kosten für die Ausführung Ihres Dienstes aufgrund des erhöhten Datendurchsatzes erhöhen.
Sie müssen dann entscheiden, wie Sie am besten mit Ihren Servern kommunizieren, um sicherzustellen, dass diese geschützt sind. Dies ist wichtig, um zu verhindern, dass dieselben Probleme mit Ihrer internen API erneut auftreten. Die beste Faustregel, die ich geben kann, ist, wegen der Bedrohung durch den Mann in der Mitte kein Geheimnis direkt zu übermitteln. Stattdessen können Sie den Datenverkehr mit Ihrem Geheimnis signieren und die Integrität aller an Ihren Server gesendeten Anforderungen überprüfen. Eine Standardmethode hierfür ist die Berechnung eines HMAC der Nachricht, die auf einem Geheimnis verschlüsselt ist. Ich arbeite in einem Unternehmen, das ein Sicherheitsprodukt hat, das auch in diesem Bereich tätig ist, weshalb mich solche Dinge interessieren. In der Tat ist hier ein Blog- Artikel von einem meiner Kollegen, der das meiste davon behandelt.
Wie viel soll ich tun?
Bei solchen Sicherheitsratschlägen müssen Sie eine Kosten-Nutzen-Entscheidung darüber treffen, wie schwer es für jemanden sein soll, einzudringen. Wenn Sie eine Bank sind, die Millionen von Kunden schützt, unterscheidet sich Ihr Budget völlig von dem, der eine App in ihrem Kunden unterstützt Freizeit. Es ist praktisch unmöglich zu verhindern, dass jemand Ihre Sicherheit verletzt, aber in der Praxis benötigen nur wenige Menschen alle Schnickschnack, und mit einigen grundlegenden Vorsichtsmaßnahmen können Sie einen langen Weg zurücklegen.
quelle
Die sicherste Lösung besteht darin, Ihre Schlüssel auf einem Server zu belassen und alle Anforderungen, die diesen Schlüssel benötigen, über Ihren Server weiterzuleiten. Auf diese Weise verlässt der Schlüssel niemals Ihren Server. Solange Ihr Server sicher ist, gilt dies auch für Ihren Schlüssel. Natürlich verursacht diese Lösung Leistungskosten.
quelle
Halten Sie das Geheimnis in sich
firebase database
und erfahren Sie es, wenn die App startet. Es ist weitaus besser, als einen Webdienst anzurufen.quelle
Was auch immer Sie tun, um Ihre geheimen Schlüssel zu sichern, wird keine echte Lösung sein. Wenn Entwickler die Anwendung dekompilieren können, gibt es keine Möglichkeit, den Schlüssel zu sichern. Das Ausblenden des Schlüssels ist nur Sicherheit durch Dunkelheit, ebenso wie die Verschleierung des Codes. Das Problem beim Sichern eines geheimen Schlüssels besteht darin, dass Sie zum Sichern einen anderen Schlüssel verwenden müssen und dieser Schlüssel auch gesichert werden muss. Stellen Sie sich einen Schlüssel vor, der in einer Box versteckt ist, die mit einem Schlüssel verschlossen ist. Sie stellen eine Kiste in einen Raum und schließen den Raum ab. Sie müssen einen weiteren Schlüssel sichern. Und dieser Schlüssel wird immer noch in Ihrer Anwendung fest codiert.
Wenn der Benutzer keine PIN oder Phrase eingibt, kann der Schlüssel nicht ausgeblendet werden. Dazu müsste jedoch ein Schema für die Verwaltung von PINs außerhalb des Bandes vorhanden sein, dh über einen anderen Kanal. Sicherlich nicht praktisch zum Sichern von Schlüsseln für Dienste wie Google APIs.
quelle
Alte alte Post, aber immer noch gut genug. Ich denke, es wäre großartig, es in einer .so-Bibliothek zu verstecken, natürlich mit NDK und C ++. .so-Dateien können in einem Hex-Editor angezeigt werden, aber viel Glück beim Dekompilieren von: P.
quelle
Der einzig wahre Weg, diese privat zu halten, besteht darin, sie auf Ihrem Server zu belassen und die App alles an den Server senden zu lassen, und der Server interagiert mit Dropbox. Auf diese Weise verteilen Sie Ihren privaten Schlüssel NIEMALS in einem beliebigen Format.
quelle
Basierend auf bitteren Erfahrungen und nach Rücksprache mit einem IDA-Pro-Experten besteht die beste Lösung darin, einen wichtigen Teil des Codes in eine DLL / SharedObject zu verschieben, ihn dann von einem Server abzurufen und zur Laufzeit zu laden.
Sensible Daten müssen verschlüsselt werden, da dies sehr einfach ist:
quelle