Geheimhaltung eines Strings im (offenen) Quellcode


50

Ich habe die Entwicklung einer App für Android abgeschlossen und beabsichtige, sie mit der GPL zu veröffentlichen - ich möchte, dass sie Open Source ist. Die Art der Anwendung (eines Spiels) besteht jedoch darin, dass sie Rätsel stellt und die Antworten in die Zeichenfolgenressource codiert. Ich kann die Antworten nicht veröffentlichen! Mir wurde gesagt, ich solle versuchen, Passwörter sicher zu speichern - aber ich habe nichts Passendes gefunden.

Ist es möglich, meinen Quellcode mit einem versteckten, verschlüsselten oder auf andere Weise verdeckten String-Array zu veröffentlichen? Vielleicht durch das Lesen der Antworten aus einer Online-Datenbank?

Aktualisieren

Die Lösung von Yuval Filmus unten hat funktioniert. Als ich es zum ersten Mal las, war ich mir immer noch nicht sicher, wie ich es machen sollte. Ich habe einige Lösungen für die zweite Option gefunden: Speichern der Hash-Lösung in der Quelle und Berechnen des Hashs, wenn der Benutzer dies errät. Um dies in Javascript zu tun, gibt es die crypto-js Bibliothek unter http://code.google.com/p/crypto-js/ . Verwenden Sie für Android die MessageDigest- Funktion. Es gibt eine Anwendung (auf fdroid / github) namens HashPass, die dies tut.


11
Ich frage mich, wie aktuell das hier ist. In jedem Fall ist es möglicherweise besser für die Informationssicherheit geeignet .
Raphael

2
@YuvalFilmus Lassen Sie sich nicht von "Hot Question" -Stimmen täuschen. Aber Punkt genommen.
Raphael

4
Die wichtigen Details, die hier fehlen, sind: Möchten Sie nur die Benutzerantworten überprüfen oder möchten Sie auch die richtige Antwort drucken können? Benötigen Sie irgendwelche Unschärfen oder gibt es nur einen klaren begrenzten Satz korrekter Antworten (mit denen Sie die Benutzerantwort nacheinander anhand dieses Satzes überprüfen können)?
Hyde

4
Alle Antworten fragen, welches Problem Sie lösen möchten. Warum können Sie die Antworten nicht veröffentlichen?
Rhymoid

1
Was muss Ihr Code mit diesen Zeichenfolgen tun können? Muss es in der Lage sein, sie zu entschlüsseln? Oder reicht es aus, Strings mit ihnen zu vergleichen?
David Schwartz

Antworten:


83

Sie haben mindestens zwei Möglichkeiten, je nachdem, welches Problem Sie lösen möchten.

Wenn Sie möchten, dass unschuldige Leser Ihres Codes nicht versehentlich die Antworten erhalten, oder wenn Sie es den Benutzern zumindest etwas schwer machen möchten, damit sie nicht in Versuchung geraten, können Sie die Lösungen verschlüsseln und den Schlüssel als Teil Ihres Codes speichern, z Ergebnis einiger Berechnungen (um es noch schwieriger zu machen).

Wenn Sie verhindern möchten, dass Benutzer die Antwort abrufen, können Sie eine Einwegfunktion oder im Fachjargon eine Hash-Funktion verwenden . Speichern Sie einen Hash der Antwort, und Sie können testen, ob die Antwort korrekt ist, ohne dass Sie die Antwort ableiten können, ohne sie zuerst zu finden. Dies hat den Nachteil, dass es schwieriger ist, nach einer Antwort zu suchen , die der richtigen nahe kommt , obwohl es auch für dieses Problem einige Lösungen gibt.


9
Eine Sache, die ich hinzufügen möchte, ist, dass, wenn Sie noch mehr Sicherheit benötigen, jede Antwort wahrscheinlich mit einem anderen Salz gesalzen werden sollte. Dies vermeidet einen Wörterbuchangriff auf alle Antworten gleichzeitig. Wenn Sie sehen möchten, wie es die "echten" Kryptoleute machen, werfen Sie einen Blick auf das String-to-Key-System in OpenPGP .
Pseudonym

1
Hashes im Code zu halten bedeutet, dass alle Informationen statisch sind und Salz enthalten. Als Ergebnis halte ich es für vernünftig, wenn der Antwortraum groß genug ist (wie etwa der gesamte Bereich von 32-Bit-Ganzzahlen), andernfalls (dh im Fall von Multiple-Choice-Fragen) würde die Regenbogentabelle schnell die richtigen Antworten geben.
Alexei Levenkov

3
Wie Alexei betont, werden Ihre möglichen Eingaben, wenn sie sich über einen kleinen Bereich erstrecken, durch das Speichern der Antworten im Code für jeden entschlossenen Angreifer geöffnet - und ich vermute, die meisten Rätsel haben eher kleine Zustandsräume, da ihre Antworten im Allgemeinen lauten müssen entweder Wörter oder relativ kleine Zahlen. Sie können hashen oder verschlüsseln, um unschuldige Fehler zu vermeiden, aber niemand kann verhindern, dass jemand die Antwort bekommt, der sie wirklich will. (Außerdem könnten sie einfach jemanden fragen, der Ihr Rätsel bereits gelöst hat!)
Chris Hayes,

4
Um dem entgegenzuwirken, was Chris erwähnt, können Sie einen sehr langsamen Hashing-Prozess auswählen, der beispielsweise 100 ms dauert (dies ist der Ansatz einiger PK-Standards). Dies ist aus Sicht des Benutzers immer noch sehr schnell, erschwert jedoch die Aufzählung erheblich.
Yuval Filmus

12
@YuvalFilmus Bis zu einem gewissen Grad. Wenn dein Rätsel endet mit "War Jan, Joe oder Jane der Verbrecher?" dann wird es sehr einfach sein zu zählen, selbst wenn Sie den Hash eine ganze Minute dauern lassen. Wenn nicht das gesamte Spiel in diesem Sinne geschrieben ist und alle Fragen sehr offen sind, wird dies ein Problem darstellen. Aber ja, wenn Ihre Fragen so offen sind , dass der Zustandsraum groß genug ist, können die Antworten geschützt werden.
Chris Hayes

28

Sie haben zwei drei Möglichkeiten:

Halten Sie die Antworten vom restlichen Quellcode getrennt

Wenn Sie möchten, dass Ihr Code Open Source ist, die Antworten jedoch nicht Open Source, dann öffnen Sie den Code für die Anwendung ohne die Fragen und Antworten, wobei die Fragen und Antworten ein separates Closed-Source-Plugin sind. oder Datendatei. Ihre Android-App würde beide in einer einzigen App bündeln.

Tragen Sie die Antworten in Ihren Quellcode ein

Wenn Sie alternativ die Fragen und Antworten als einen Kernbestandteil dessen betrachten, was Sie als Open-Source-Lösung wünschen, sollten Sie die Antworten im Quellcode ablegen, vorzugsweise ohne Verschleierung, damit andere sie lesen und ändern können . Die Verschleierung von Quellcode, so dass er nicht verstanden und modifiziert werden kann, entspricht nicht wirklich den Prinzipien von Open Source Code.

Stellen Sie die Antworten auf einen Server im Internet

Mit beiden oben genannten Lösungen kann in beiden Fällen jemand, der Ihre App heruntergeladen hat, die Antworten herausfinden, ohne Ihr Programm abzuspielen. Dabei spielt es keine Rolle, wie Sie Ihre Antworten verschleiern / verschlüsseln, wenn Ihr Programm die Antwort ohne zusätzliche Informationen identifizieren kann kann ein Mensch Ihre kompilierte App untersuchen.

Wenn Sie wirklich sicherstellen möchten, dass niemand die Antworten herausfinden kann, besteht die einzige echte Option darin, ihnen keine Antworten zu geben und die App einen Webservice anrufen zu lassen, usw., wann immer sie die Antwort wissen möchten. Die App sollte die Antwort senden, die der Benutzer eingegeben hat, und der Webservice sollte der App mitteilen, ob die Antwort korrekt ist oder nicht. Auf diese Weise kann der Benutzer erst dann sagen, wie die Antwort lautet, wenn er bereits die richtige Antwort hat (kurz von Brute-Forcing des Web-Service, den Sie erkennen und schützen können).

Wenn Sie nach Wegen suchen, um Ihre Antworten zu verschleiern, deutet das darauf hin, dass Sie Ihre Antworten nicht unbedingt als Open Source-Lösung anbieten möchten, und Sie sollten daher die ersten Optionen in Betracht ziehen.

Wenn es kritisch ist, dass der Benutzer die Antwort nicht im Voraus findet, ist die dritte Option Ihre einzige echte Wahl. Ich kann mir jedoch nur schwer vorstellen, in welchem ​​Szenario dies den Aufwand wert wäre, nicht zuletzt, weil es Ihre Benutzer daran hindert von der Verwendung Ihrer App ohne Internetverbindung.


8
Das Q & A muss nicht einmal ein Plugin sein, es kann eine einfache Datendatei sein. Eingabedatendateien sind nicht notwendigerweise Teil der lizenzierten Software und können unter einer eigenen separaten Lizenz abgedeckt werden. Solange Sie eine (andere) Beispieldatendatei zur Verwendung mit dem Quellcode bereitstellen, behindern Sie nicht die freie Verwendung der Quelle oder der aus dieser Quelle kompilierten Programme und sollten daher nicht gegen die GPL verstoßen.
Doktor J

Ich bin mir nicht sicher, ob das Problem wirklich gelöst ist - ob die Antworten im Code verschlüsselt und fest codiert sind oder als separate Datei verteilt werden, der Code muss immer noch in der Lage sein, die Antworten zu entschlüsseln, damit jeder, der seine App herunterlädt, was tun kann Der Quellcode tut dies, um zu den Antworten zu gelangen. (es sei denn, sie sind gehasht, wie in einer anderen Antwort vorgeschlagen)
Johnny

1
Wenn das Ziel darin besteht, Antworten zu überprüfen, und diese nicht angezeigt werden müssen, kann dies genauso erfolgen wie bei Kennwörtern mit einem One-Way-Hash.
James Ryan

@Justin, danke für deine Antwort und deine Kommentare, ob es Open Source ist, sind interessant. Ich denke, dass das Ausblenden der Antworten nicht dazu gedacht ist, den Quellcode oder die Funktionsweise der Anwendung zu verschleiern, sondern die Integrität der Herausforderung zu bewahren. Kryptographie ist, wie sich herausstellt, ein wunderbares Mittel, um Rätsel zu verbreiten, ohne dabei zu sein, wenn der Benutzer vermutet ("Ist es das, ist es das?")
Nevermore

4

Wenn das Ziel darin besteht, Zeichenfolgen vor dem zufälligen Lesen des Quellcodes zu verbergen, diese jedoch offen zu halten, damit andere Personen problemlos ihre eigenen Änderungen vornehmen können - zum Beispiel, wenn Sie die Quelle in einem Textabenteuer veröffentlichen und keinen beschreibenden Text anzeigen möchten was einen Spoiler ausmachen würde, dann benutze etwas reversibles wie rot13.

Tatsächlich könnten Sie alle Ihre Übersetzungsdateien rot13 und sie sofort wieder umdrehen.

Das hält den offenen Geist. Zufällige "magische" Hashes sind nicht wirklich programmiererfreundlich.


4
Denken Sie daran, dass viele GeoCaching-Leute unter uns rot13 fast so flüssig lesen wie das Original.
yo '

4

Open Source erfordert, dass der Quellcode veröffentlicht und verfügbar ist, nicht die Spieldaten. So können Sie die Daten einfach in eine andere Datei einfügen und diese nicht veröffentlichen. Fügen Sie etwas Krypto hinzu, wenn Sie das gelegentliche Lesen der Datei verhindern möchten. Ich bezweifle, dass eine starke Krypto für Ihre Anwendung erforderlich ist.


1
In welchem ​​Sinne können Sie die Spieldaten "nicht veröffentlichen"? Das Spiel muss auf diese Daten zugreifen können, damit jeder, der über eine Kopie des Spiels verfügt, über eine Kopie der Daten verfügt. Genau das ist Publizieren: Publizieren.
David Richerby

1
@DavidRicherby Hängt davon ab, was Sie veröffentlichen und was enden soll. Das Spiel oder Ihre Engine, mit der viele ähnliche Spiele erstellt werden könnten? Erlauben Sie den Spielern, Ihr Spiel zu manipulieren, den Code auf Sicherheitslücken zu untersuchen oder nur Komponenten wiederzuverwenden? Wenn Ihre Benutzeroberfläche so einfach ist wie "CSV mit q & a + program = game", ist es meines Erachtens denkbar, nur das Programm und nicht die CSV zu veröffentlichen.
Raphael

1
@Raphael Aber das Verteilen eines Spiels, das aus einer ausführbaren Datei und einer Datei mit einfachen Textdaten besteht, erreicht nicht das Ziel, die Antworten geheim zu halten. Wenn Sie eine verschlüsselte Version der Datendatei vorschlagen möchten, ist dies in Ordnung, sofern alle verstehen, dass dies nur Sicherheit durch Unklarheit ist (der Schlüssel befindet sich in der Quelle). Aber dann kommen wir zur Frage, ob der Klartext der Datei einen Quellcode im Sinne der GPL darstellt, und an dieser Stelle wird die Frage eher zur Interpretation der GPL als zur Frage der Informatik.
David Richerby

@DavidRicherby: Einverstanden. Obwohl IANAL, bezweifle ich sehr, dass eine Datendatei, die aus Rätseln und deren Antworten besteht, als ein so wesentlicher und unersetzlicher Teil des Programms angesehen wird, dass sie nicht separat lizenziert werden kann - insbesondere, wenn Sie eine unverschlüsselte Beispieldatendatei in das Programm aufgenommen haben Die Quelldistribution sowie Anweisungen zum Ändern und Verschlüsseln, falls erforderlich, machen deutlich, dass jeder mit dem Quellcode tatsächlich seine eigenen benutzerdefinierten Datendateien erstellen und mit dem Programm verwenden kann.
Ilmari Karonen

4

Warum sollten Sie Ihre Antworten in Ihrem GPL-Quellcode speichern, wenn Sie nicht möchten, dass Ihre Benutzer sie kennen? Auch wenn sie derzeit nicht bekannt sind oder leicht zu knacken sind, können (und werden) sie es in Zukunft sein.

Verwenden Sie eine externe Datenbank, anstatt sie in Ihrer App zu speichern. Erstellen Sie einen kleinen Webdienst, der die Antworten mit denen in Ihrer Datenbank vergleicht. Lassen Sie dann Ihre Anwendung diesen Webservice aufrufen, wann immer dies überprüft werden muss. Das Hauptproblem ist, dass Sie aufgrund der Notwendigkeit eines Internetzugangs an Geschwindigkeit und potenzieller Benutzerbasis verlieren. Ihre App-Lizenz sollte nur für die App selbst gelten, nicht für den Webservice.

Sie können Ihre Antworten auch einfach in eine kleine Datenbank eingeben und in Ihr Programm einfügen. Soweit mir bekannt ist, bezieht sich die GPL nur auf den Quellcode, nicht auf Daten, die Ihre App speichert. Darin könnte ich mich jedoch irren.


1
"Soweit ich weiß, gilt die GPL nur für den Quellcode, nicht für die Daten, die Ihre App speichert." Nun, die GPL sagt: "Sie müssen das gesamte Werk als Ganzes unter dieser Lizenz an jeden lizenzieren, der in den Besitz einer Kopie kommt." Vielleicht müssen wir uns jetzt entscheiden, ob die Daten Teil der "gesamten Arbeit" sind. Aber tatsächlich gelten alle Einschränkungen der GPL (einschließlich dieser) nur für Lizenznehmer. Es ist schön, dass Lizenzgeber sich auch an die GPL halten, aber sie sollten sich keine Sorgen über einen Besuch der Urheberrechtspolizei machen müssen.
Peter Ford

1

Denken Sie daran, dass die Datenbank auch dann dupliziert werden kann, wenn Sie sie auf einem Remote-Webserver speichern, indem Sie einfach alle korrekten Schlüssel / Wert-Paare aufschreiben, die angezeigt wurden. Im Allgemeinen sollten mobile Apps versuchen, keine Fehler zu verursachen oder nicht mehr zu funktionieren, da das Netzwerk ausgefallen ist (verwenden Sie Messaging in der Warteschlange und "Aktualisieren, wenn Sie können").

Wenn Sie also eine lokale Datenbank möchten, die jedoch nicht unbedingt entschlüsselt werden soll, können Sie einen Bloom-Filter verwenden (um zu vermeiden, dass Sie mit einem Netzwerk kommunizieren oder lokal über eine große entschlüsselte Datenbank verfügen). So funktionierte die Rechtschreibprüfung, wenn der Speicherplatz sehr knapp war.

Wenn Sie also Frage / Antwort-Paare wie folgt in den Filter einfügen:

Hash (NormalizeString (Frage [n])) + Hash (NormalizeString (Antwort [n]))

Wenn Sie fragen, ob "Capitol of Virginia? Richmond" im Set ist, wird entweder "definitiv nein" oder "mit ziemlicher Sicherheit ja" geantwortet. Wenn Sie zu viele Fehlalarme erhalten, vergrößern Sie die Datenbank.

Sie könnten eine riesige Datenbank auf kleinstem Raum haben, vorausgesetzt, der Benutzer schreibt die Frage und Antwort genau so, wie Sie es erwarten. Die Datenbank klein zu halten hilft bei Updates, da diese wahrscheinlich über drahtlose Netzwerke übertragen werden müssen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.