Mittwoch, 18. Juli 2012

Tagescode

Voraussetzung: "Einstieg in Lua“
Wer kennt das nicht, man erstellt einen aufwendigen Cache, überlegt sich aufwendige Fragen und knifflige Aufgaben. Der FTF dauert auch einige Zeit, da es ja ein sehr aufwendiger Cache ist.
Cachefund Nr. 2 und 3 drudeln dann schon schneller ein und spätestens wenn Person X den Cache gefunden hat, steigt die Anzahl der Funde exponentiell an. Person X gehört nämlich zur lokalen Mystery-Tausch-Szene, die über eMail-Verteilerlisten Finalkoors von aufwändig gestalteten Döschen weiterverbreiten.
Wer diesen Misbrauch bei einem Wherigo verhindern oder besser gesagt erschweren möchte, der kann eine Art Checkcode einbauen, den man am Ende des Spiels erhält und in den Log schreiben bzw. per eMail senden muss. Es geht in diesem Beitrag nicht darum zu klären, ob dies bei einem WIG zulässig ist, bzw. ob man den Misbrauch kontrollieren sollte oder die Spielverderber einfach sich selber bescheißen lassen sollte. Diese Fragen kann man gerne in bekannten Foren diskutieren.

Abbildung 1: Generierung eines Tagescodes
Hier geht es lediglich um die technische Umsetzung eines Tagescodes. D.h ein Code, der nur für einen Tag lang gültig ist, der (relativ) eindeutig ist und was ganz wichtig ist, den man nicht zurückrechnen kann, um den Code für den nächsten Tag zu berechnen.
Man nennt so einen Vorgang eine Einwegfunktion. "Leicht" zu berechnen aber "schwer" umzukehren. (Siehe http://de.wikipedia.org/wiki/Einwegfunktion).
Abb. 1 zeigt die Erstellung einer Einwegfunktion mittels Multiplikation und ganz wichtig einer Modulo Division. Heute kommt als Ergebnis 5919, morgen 6466 und übermorgen 476. Wer kann daraus den Code für nächste Woche Montag berechnen? (Streng genommen wäre es möglich, wenn man nicht nur drei sondern hunderte Werte hätte, aber der zu betreibende Aufwand stände in keinem Verhältnis zum Nutzen)
Nachtrag vom 20.07: Leider hat sax (siehe Kommentar) völlig recht. Man kann relativ leicht a und b berechnen. Es muss nur die Formel bekannt sein. D.h. um die Sache etwas sicherer zu machen, darf die Formel nicht bekannt sein. Addiert z.B nach dieser Rechnung einen Wert c auf das Ergebnis multipliziert es mit d und rechnet anschließend wieder Modulo e. Das ist zwar immer noch nicht wasserdicht, aber wenn ihr nicht zwei Moduloschritte sondern 3, 4 oder 5 Mal den Rest nehmt, wird es immer schwieriger auf die Formel zu kommen. Ich werde demnächst ne Lösung mittels Hashfunktion, MD5 oder Public-Key als asymmetrisches Verschlüsselungsverfahren untersuchen und vorstellen. Immer vorausgesetzt, dass auch das langsame Oregon die Daten schnell genung berechnen kann.

Wenn man sich die Abbildung genauer betrachtet, wird man feststellen, dass auch Daten wie 31. April oder 30. Februar erfasst wird, aber das stört uns nicht. Wichtig ist nur, dass jeder Tag dabei ist und dass der Code eindeutig ist. Das mit der Eindeutigkeit stimmt nicht ganz hundertprozentig, aber je größer die beiden Zahlen für die Division und die Modulo Rechnung sind, desto unwahrscheinlicher ist es, dass im Log zweimal der gleiche Code auftaucht.

Abbildung 2: In drei Schleifen wird für jeden Tag, Monat und Jahr der Tagescode erzeugt und ausgegeben
Man sollte die beiden Zahlen auf jeden Zahlen aus dem Tutorial abändern, denn sonst kann jeder den Code berechnen.
Da wir eine Einwegfunktion benutzen, können wir natürlich anhand des vom User eingegebenen Codes nicht zurückrechnen, ob das Datum und damit der Code korrekt ist. Abhilfe schafft hier eine Tabelle, die wir uns erzeugen, damit können wir für den entsprechenden Tag nachschauen, ob der Code korrekt ist.
Abb. 2 zeigt drei ineinander geschachtelte Schleifen, die für die Jahre 2012, 2013 und 2014 für jede Kombination aus 31 Tagen und 12 Monaten den Code ausrechnen und mittels print ausgeben. Natürlich kann man die Funktion noch verfeinern, dass der 31. April nicht mit ausgegeben wird, es würde unsere Funktion aber unverhältnismäßig komplex werden lassen.
Da wir die print Ausgabe im WIG-Player nicht sehen können, bedienen wir uns des Urwigo-Simulator um die Tabelle anzuschauen. Einfach das Projekt CodeGenerator mit F5 starten und auf den Reiter "Lua Debug" klicken, um die Werte zu betrachten, zu markieren und in eine Textdatei zu sichern.

Abbildung 3: So gelangt man zur Print-Ausgabe im Simulator.
Wem das noch nicht genug Kontrolle ist -schließlich könnten so immer noch Rudelteilnehmer loggen, wenn nur einer die Aufgabe erfüllt hat- kann man noch den Username (Zugriff in lua mittels Player.Name) mit in den Code einkodieren. Dazu nutzen wir die string.byte(myString, position) Funktionalität, die die einzelnen Buchstaben in ihren ASCII-Code umwandeln. string.byte("ABCDE",1) liefert z.B 65, da dies der Code für das erste Zeichen im String, nämlich A ist. Um den Usernamen komplett zu erfassen, kann man über alle Buchstaben iterieren und die Summe der ASCII-Werte der Variablen days aus Abb. 1 hinzufügen. Doch Vorsicht: Hierdurch steigt der Testaufwand um ein Vielfaches, denn nicht nur Groß- und Kleinbuchstaben ("klein a" besitzt den ASCII-Code 97) müssen abgedeckt werden, auch Leerzeichen Umlaute, Zahlen und alle anderen Zeichen, die Groundspeak als Usernamen erlaubt, müssen durch die Funktion erfasst werden. Ebenso steigt der Wartungsaufwand für den Cache, da man bei jedem Log, manuell den Namen in den Codegenerator eingeben muss.
Wer sich hierfür interessiert, kann mir ne Mail zukommen lassen, damit er ein kleines Java-Progrämmchen erhält, mit dem Eingabe und Codeausgabe schneller gehandelt werden können. Zu bedenken ist auch, dass man die Cachesuche erheblich erschwert: Jeder WIG-Spieler muss sich das Cartridge selbst herunterladen und dabei auf wherigo.com mit dem Usernamen eingeloggt sein, mit dem er auf geocaching.com loggen möchte. Außerdem schließt man so auch alle Cacher aus, die keine WIG-fähiges Gerät besitzen und so nicht an den Code kommen.
Mir persönlich wäre es definitiv zu viel Kontrolle, aber das muss jeder selbst entscheiden. Ich möchte lediglich auf die technische Möglichkeit hinweisen.

Kommentare:

  1. Du solltest bei deiner ganzen Checkerei bedenken, daß derjenige den Cache loggen darf, der im physikalischen Logbuch steht, egal, ob das Wherigo finalisiert wurde oder nicht.

    AntwortenLöschen
    Antworten
    1. Wie war das noch im Text...
      "Es geht in diesem Beitrag nicht darum zu klären, ob dies bei einem WIG zulässig ist"

      Löschen
    2. Man könnte es im Listing ja auch harmloser gestalten: "Loggen darf natürlich jeder der im Logbuch steht, als Iron-Man-Cacher kannst du mit dem Code im Log beweisen, dass du die Aufgabe auch wirklich erfüllt hast"

      Löschen
    3. Naja, ich frage mich nur, ob es wirklich diese Mühe wert ist (egal ob zulässig oder nicht).
      Ich gebe auch zu bedenken, daß der Spaßfaktor tatsächlich extrem leiden könnte, wenn man einen Code pro Cacher und gespieltes Wherigo haben will. Beispiel: Familie mit 4 Accounts hat genau ein Gerät.
      Auch dann, wenn einen die Cartridges in unterschiedliche Richtungen schicken, ist es ziemlich unspaßig, wenn jeder sein eigenes Cartridge spielen muß, statt einfach gemeinsam mit einem Gerät zu arbeiten.
      Ich kann Caches nicht leiden, wo mich Owner bevormunden wollen und mir vorschreiben wollen, wie ich sie zu lösen habe. Das reizt geradezu dazu, einen Alternativweg zur Lösung zu finden.

      Löschen
    4. Ich sehe die Sache mit der Bevormundung ähnlich und habe auch in keinem meiner Wherigos einen solchen Code eingebaut. Im Gegenteil, bei den Einsteigervorträgen rate ich den Teilnehmern davon ab, zu viel Kontrollhürden wie Passwort im Logbuch u.ä. einzubauen.
      Da mich ein befreundeter Cacher fragte, wie man einen Tagescode erstellen kann, dachte ich es wäre auch für andere Programmierer interessant.

      Löschen
    5. Diesen Tagescode kann man doch in ein paar Minuten knacken, wenn man die zugrunde liegende Gleichung: days*a %b kennt, reichen die Werte "heute 5919, morgen 6466 und übermorgen 476" volkommen aus. Mit hoher Wahrscheinlichkeit reichen auch schon die Werte von 2 aufeinanderfolgenden Tagen aus, um den Wert des dritten Tages vorherzusagen.

      Der Tageswert unterscheidet sich vom Vortag immer um a, es sei denn die Modulo Funktion schlägt gerade zu, was genau dann passiert, wenn zwichen days*a und (days+1)*a ein ganzzahliges Vielfaches von b liegt.
      Solange man a << b wählt, sieht man der Zahlenfolge ihren Charackter förmlich an. Wenn a und b in der selben Größenordnung liegen, wird es schon wesentlich schwieriger.

      Löschen
    6. Oh, shame on me,
      da hast du leider vollkommen recht. Da hab ich gepennt. Ich werd mal untersuchen, wie es mit ner zweistufigen Modulo Funktion aussieht ( day * a % b) * c % d
      oder als alternative doch den Hashwert berechnen. Gesetz den Fall, dass das Oregon dies noch zeitig hinbekommt.

      Löschen
  2. Hallo Krolock,

    hast du MD5 oder Hash schon mal mit Urwigo probiert?

    AntwortenLöschen
    Antworten
    1. Nein noch nicht, ich muss mal schauen, ob lua da bereits Bibliotheken mitbringt (die aber auch von allen WIG Player zur Verfügung gestellt werden) oder ob man den Code selbst einfügt.

      Löschen
    2. Ok Danke für die schnelle Antwort.

      Schade, im Grunde ist es ja auch anders lösbar MD5 oder Hash lässt sich halt auf PHP & Co. schön auswerten. Mein Ziel ist es eine Art Capcha zu bauen in dem User.name; Punktzahl und Spielzeit vereint werden. Quasi: Olli39012 (Olli 390Punkte 12min) Das bilden diese "Codes" ist nicht schwer. Schön wär halt wenn diese irgendwie verschlüsselt währe. Im Grunde nur aus Interesse am progen...

      Urwigo stellt doch auch os.clock() bereit. Ist das gleich zusetzen mit Unix-Timestamp?

      Löschen
  3. os.clock() ist ne ganz heiße Kiste bei der WIG-Programmierung. Da ist vieles abhängig von dem Player auf dem das Script läuft. Am besten schaust du mal in den Geoclub. Da gibt es im Wherigo-Forum viele Threads zum Thema Systemzeiten.
    Falls du ne Verschlüsselung mit lua mal programmieren solltest, wäre ich über nen Statusbericht (oder vllt nen Gastbeitrag hier im Blog?) sehr erfreut

    AntwortenLöschen
    Antworten
    1. Ok Danke. Wenn ich was habe dann schreib ich es.

      Löschen