Im Geiste des Underhanded-C-Wettbewerbs starte ich einen Underhanded-Code-Wettbewerb. Das Ziel dieses Wettbewerbs ist es, Code einfach zu implementieren und dabei einen schändlichen Fehler zu verbergen.
Der Wettbewerb
Sie sind ein geheimer russischer Maulwurf, der in der IT-Abteilung einer amerikanischen Spionageagentur arbeitet. Ihr amerikanischer Chef hat Sie gerade gebeten, einen Passwort-Hashing-Algorithmus für die Verschlüsselung geheimer Nachrichten zu implementieren.
Ihr Chef möchte, dass Sie die folgende Funktion implementieren:
f: String -> byte[16]
Das konvertiert ein Passwort in eine 16-Byte-Menge, die als AES-Schlüssel verwendet werden kann. Ihr Chef möchte eine sichere Funktion, was in diesem Zusammenhang bedeutet, dass unterschiedliche Kennwortzeichenfolgen mit überwältigender Wahrscheinlichkeit unterschiedliche Ergebnisse erzeugen sollten. Zum Beispiel wäre die Rückgabe des MD5- Hash der Eingabe eine einfache Implementierung von f
.
Natürlich möchte Ihr echter Chef der russischen Spionageagentur, dass Sie diesen Prozess untergraben. Ihre Aufgabe ist es, f
so zu implementieren , dass die Russen alle geheimen Nachrichten entschlüsseln können, die mit Schlüsseln verschlüsselt wurden, die von zurückgegeben wurden f
.
Dazu müssen Sie implementieren f
, dass nur eine kleine Teilmenge der 2 ^ 128 möglichen Ausgaben zurückgegeben wird. Insbesondere f
müssen Sie höchstens 2 ^ 16 unterschiedliche Ergebnisse zurückgeben, damit die Russen für jede verschlüsselte Nachricht, die sie entschlüsseln möchten, eine einfache Brute-Force-Suche nach dem richtigen Schlüssel durchführen können.
Denken Sie jedoch daran, dass Spionage mit der Todesstrafe verbunden ist. Um nicht erwischt zu werden, f
muss Ihre Funktion mindestens 2 ^ 8 verschiedene Ergebnisse generieren, sodass eine flüchtige Überprüfung einiger Ausgaben von f
wahrscheinlich kein Duplikat ergibt . Und am wichtigsten ist, dass der Code, den Sie einführen, um den Bereich f
einzuschränken, nicht absichtlich, sondern ungewollt aussieht. Wenn Sie jemals in einen Gerichtssaal gebracht werden, muss es begründete Zweifel geben, ob Sie den Fehler absichtlich oder versehentlich eingeschleppt haben.
Beurteilen
Ich und zwei andere, die ich rekrutiere, beurteilen die Einträge (senden Sie mir eine E-Mail, wenn Sie beurteilen möchten). Ich biete ein Reputationsguthaben von 200 für den siegreichen Beitrag. Einsendungen müssen bis zum 1. Mai hochgeladen sein.
Bei der Beurteilung werden folgende Kriterien berücksichtigt:
- Entspricht
f
der Spezifikation, erzeugt also zwischen 2 ^ 8 und 2 ^ 16 mögliche Ausgaben. Denken Sie nicht, dass dies harte Grenzen sind, aber wir ziehen Punkte ab, wenn Sie zu weit außerhalb der Reichweite sind. - Ist der Fehler plausibel auf einen unbeabsichtigten Fehler zurückzuführen?
- Sehen die Ausgaben von
f
zufällig aus? - Je kürzer Ihre Implementierung ist
f
, desto besser. - Je klarer Ihre Implementierung
f
, desto besser.
Anmerkungen
Sie können eine beliebige Sprache verwenden, um Ihren Code zu implementieren. Sie versuchen, einen Fehler in der Öffentlichkeit zu verbergen, daher wird kein verschleierter Code empfohlen.
Vielleicht möchten Sie einen Blick auf einige der vorherigen Gewinner des Underhanded C-Wettbewerbs werfen , um ein Gefühl dafür zu bekommen, was eine gute Einreichung ausmacht.
Eingabezeichenfolgen können in ASCII-Form (32 bis einschließlich 126) gedruckt werden. Sie können eine angemessene maximale Länge annehmen, wenn Sie möchten.
quelle
Antworten:
C
2 ^ 16 mögliche Ausgaben (oder 2 ^ 8 mal die Anzahl der verwendeten Zeichen).
Verwendet die MD5-Implementierung von Linux (AFAIK). Dies ergibt jedoch den gleichen Hash, zum Beispiel für "40" und "42".
BEARBEITEN: Umbenannt
bcopy
inmemcpy
(natürlich vertauschte Parameter).BEARBEITEN: Konvertiert von Programm zu Funktion, um die Anforderungen besser zu erfüllen.
quelle
bcopy
Schritt passiert ... es ist ein gutes Stück Fehlleitung, da die eigentliche BSD-bcopy
Funktion hier richtig funktionieren würde.bcopy
ist. Ich werde es ändernmemcpy
, und dann wird die gleiche Implementierung gültig.C
Dies ist vielleicht nicht der auffälligste Wettbewerbsbeitrag, aber ich denke, das Folgende ist die Art von Hash-Funktion, die von jedem zu schlauen Programmierer für sich selbst hätte erstellt werden können, mit einer vagen Vorstellung der Art von Operationen, die Sie in Hash-Funktionen sehen:
Tatsächlich kann die Hash-Funktion nicht mehr als L * 2048 verschiedene Ergebnisse zurückgeben, wobei L die Anzahl der möglichen unterschiedlichen Längen der Eingabezeichenfolgen ist. In der Praxis habe ich den Code an 1,85 Millionen eindeutigen Eingabezeilen aus Handbuchseiten und HTML-Dokumenten auf meinem Laptop getestet und nur 85428 verschiedene eindeutige Hashes erhalten.
quelle
Scala:
Testen Sie, ob das Ergebnis bei ähnlichen Eingaben nicht ähnlich aussieht:
Der Fehler besteht darin, nur Primzahlen für die Codierung zu verwenden. Anstatt
Werte, mit denen wir enden
da gibt es 54 Primzahlen unter 256.
quelle
5.22e27 >> 2^16
. Es gibt keine Möglichkeit, so viele Möglichkeiten zu brachialisieren.