C Laufzeit meiner modifizierten memcmp()-implementierung

@Nai: Das wäre natürlich auch ne gute Lösung

@asdfman: wie genau sähe denn das Angriffsszenario aus (kann der Angreifer z.B. deine Prozessorauslastung auslesen oder läuft der Zugriff übers Netzwerk?) und wie groß sind denn überhaupt die Speicherbereiche, die verglichen werden sollen? Wenn es hier z.B. nur um ein 30 stelliges Passwort handelt wüsste ich sowieso nicht, wie jemand das genau genug timen könnte. Meistens nutzt man ja auch ne Hashfunktion, deren Berechnung ohnehin nochmal deutlich länger als der eigentliche Vergleich dauern dürfte.
 
Miuwa schrieb:
Da du wohl kein Echtzeit Betriebssystem nutzt und der Code auf x86 Prozessoren laufen soll ist das praktisch unmöglich ;).
Falls es dir reicht, dass es keinen vorhersehbaren Zusammenhang zwischen Pufferinhalt und Ausführungszeit gibt, würde ich wohl auch auf volatile zurückgreifen, obwohl ich nicht behaupten kann alle Implikationen genau zu kennen - bisher habe ich es nur für Registerzugriffe benutzt (wofür sie ja auch gedacht sind).
Generell würde ich aber vorschlagen: Prüfe den Assemblercode und messe selbst nach. Und wiederhole das ganze jedes Mal, wenn du Änderungen am Code vornimmst oder den Compiler updatest.

Mir war von Anfang an klar, dass meine Fragestellung vermutlich recht naiv ist und jetzt merke ich immer mehr, dass die Antwort von etlichen Faktoren abhängt, die völlig außerhalb meiner Kontrolle liegen. Deshalb schränke ich die Frage mal insofern ein, dass ich am Ende eine Funktion haben will, bei der ich so weit wie möglich diktieren kann, dass der Compiler Code generiert, der auf einem Echtzeitsystem lineare Laufzeit hätte -- Ihm also alle Ansätze wegzunehmen, meine Funktion zu verschlimmbessern. Es wäre am schönsten, einen standardkonformen Ersatz für memcmp() zu haben, damit ich die Funktion auch außerhalb des aktuellen Spezialfalles verwenden kann. Im Moment ist aber erstmal nur wichtig, dass sie erkennt, ob zwei Speicherbereiche den selben Inhalt haben, oder eben nicht.

Einen alternativen Algorithmus, den man ausprobieren könnte, wäre die Absolutwerte der Differenzen aufzusummieren und am Ende auf Null zu prüfen. Das dürfte der Compiler zwar genause optimieren, aber ich fände es verständlicher, als deine Konstruktion.
Klingt für mich nach einer Möglichkeit, der ich nachgehen könnte. Aber genau so wie du sagst, kann ich es auch nicht machen. Um den Absolutwert zu erhalten, muss geprüft werden, ob die Zahl negativ ist, was das Verhalten wieder vom Inhalt der Puffer abhängig macht. Meine erste Idee, das Problem zu eliminieren, war die Differenz bedingungslos zu quadrieren. Dadurch bekommt man garantiert einen positiven Wert. Ich gehe dabei davon aus, dass jede Multiplikation gleich lang dauert, was wieder nicht der Realität entsprechen könnte, wohl aber meiner oben genannten Einschränkung auf die Kontrolle des Compilers. Der Nachteil ist natürlich, dass man viel schneller einen Integer Overflow bekommt, als bei deinem Vorschlag. Der Angreifer müsste zwar eine Punktlandung bei 0 machen, damit die Manipulation durchgeht, aber wie schwierig das wäre, kann ich absolut nicht beurteilen.

@asdfman: wie genau sähe denn das Angriffsszenario aus (kann der Angreifer z.B. deine Prozessorauslastung auslesen oder läuft der Zugriff übers Netzwerk?) und wie groß sind denn überhaupt die Speicherbereiche, die verglichen werden sollen? Wenn es hier z.B. nur um ein 30 stelliges Passwort handelt wüsste ich sowieso nicht, wie jemand das genau genug timen könnte. Meistens nutzt man ja auch ne Hashfunktion, deren Berechnung ohnehin nochmal deutlich länger als der eigentliche Vergleich dauern dürfte.
Das Angriffsszenario ist am Ende des Tages rein fiktiv. Das Projekt dient mir als Spielplatz, auf dem ich lernen will, was es für Methoden gibt, sichere Software zu entwickeln und wie allgemein gute Praxis in dem Bereich aussieht. Es soll niemals tatsächlich zum Einsatz kommen. Implementierung von Kryptographie ist grundsätzlich ein Garant für ein Desaster, wenn man kein Experte ist und manchmal sogar wenn doch.

Das Angriffsszenario, das mich dazu brachte, diese Funktion zu bauen, findet sich auf Seite 363 Abs. 2 in Engineering Security von Gutman (das mir einmal von einem Menschen hier im Forum empfohlen wurde. Ich weiß nicht mehr, wer es war, aber danke!)
https://www.cs.auckland.ac.nz/~pgut001/pubs/book.pdf

Wenn die Laufzeit gar nicht von der Eingabe abhängen soll, würde ich folgenden Trick machen:
-Laufzeit extrem worst case abschätzen (z.B. 1 ms pro 10 kbyte)
-so lnage die worst case Laufzeit unterschritten ist wird am Ende der Funktion gewartet.
Wäre natürlich auch eine Möglichkeit, aber nicht zuverlässig. Mein Prozessor zu Hause ist deutlich schneller, als der auf meinem Server bspw. Dass die Performance unter der Bedingung, die ich mir gesetzt habe, leiden muss ist klar. Aber ich will erzwungenen Performanceverlust jetzt nicht zu dem Mechanismus machen, mit dem ich mein Ziel erreiche.
 
Statt dem Quadrieren könnte man auch versuchen einfach die Anzahl der Stellen zu zählen, die sich unterscheiden. Wenn es geht ohne dabei eine if-Abfrage benutzen zu müssen. In Assembler könnte man beide Werte subtrahieren und anschließend das Carry auf einen Zähler draufaddieren. Außerhalb der Funktion könnte man dann prüfen, ob der return-Wert größer als Null ist. Das würde es dem Kompiler zumindest schwieriger machen da etwa rauszuoptimieren.
 
Statt dem Quadrieren könnte man auch versuchen einfach die Anzahl der Stellen zu zählen, die sich unterscheiden. Wenn es geht ohne dabei eine if-Abfrage benutzen zu müssen. In Assembler könnte man beide Werte subtrahieren und anschließend das Carry auf einen Zähler draufaddieren. Außerhalb der Funktion könnte man dann prüfen, ob der return-Wert größer als Null ist. Das würde es dem Kompiler zumindest schwieriger machen da etwa rauszuoptimieren.

Ich denke mal dass man das fundamentale Problem dieses Ansatzes nie los wird:
-Du willst eine Funktion künstlich langsamer im Best Case zu machen, indem du sie dazu zwingst überschüssige Befehle auszuführen und dennoch das richtige Ergebnis zu liefern.
-Der Compiler darf jedoch prinzipiell sämtliche überschüssigen Befehle herausoptimieren und umgestalten, so lange sie das richtige Ergebnis nicht verfälschen. Dadurch werden die überschüssigen Befehle wieder herausoptimiert.

Man kann natürlich versuchen die Funktion obskurer zu machen, so dass der Compiler bei der Optimierung versagt. Garantie hat man dafür allerdings keine. Allerdings ergibt sich bei der Obskurifikation wiederum das Problem, dass der Code schwerer zu verstehen und damit fehleranfälliger wird. In der Hinsicht könnte man evtl noch versuchen FP-Befehle zu verwenden, da hier einige mathematischen Gesetze nicht mehr gelten, und der Compiler das dementsprechend schlechter optimieren kann.


Wäre natürlich auch eine Möglichkeit, aber nicht zuverlässig. Mein Prozessor zu Hause ist deutlich schneller, als der auf meinem Server bspw. Dass die Performance unter der Bedingung, die ich mir gesetzt habe, leiden muss ist klar. Aber ich will erzwungenen Performanceverlust jetzt nicht zu dem Mechanismus machen, mit dem ich mein Ziel erreiche.
Wie wäre es mit folgendem Trick:
Zuerst bei der Funktion mit zufälligen Werten den Worst-Case ermitteln, und dann so lange warten bis der Worst-Case * Sicherheitfaktor erreicht ist ?
 
Zuletzt bearbeitet:
Ich hab grad mal noch ein bisschen gegooglet und beim gcc kann man die Optimierung für bestimmte Bereiche ausschalten.

Code:
#pragma GCC push_options
#pragma GCC optimize ("O0")

int my_memcmp(const void *buf1, const void *buf2, size_t len) {
	size_t index;
	uint8_t *cbuf1 = buf1, *cbuf2 = buf2;
	int diff, ret = 0;
 
	for(index = 0; index < len; index++) {
		diff = cbuf1[index] - cbuf2[index];
		if(diff && !ret)
			ret = diff;
		else
			diff = ret;
	}
 
	return ret;
}

#pragma GCC pop_options

Das hat bei mir eben den unoptimierten Assemblercode erzeugt obwohl ich beim Kompilieren -O3 angegeben hab. Sowas gibt es vermutlich auch für andere Compiler, aber ich denke das ist ein Anfang.

Edit: http://stackoverflow.com/questions/2219829/how-to-prevent-gcc-optimizing-some-statements-in-c da ist auch noch eine andere Möglichkeit die ebenfalls funktioniert.
 
Zuletzt bearbeitet:
Gerade kurz wach geworden. Deshalb knapp, bevor ich mich wieder hinlege:

daemon777 schrieb:
Statt dem Quadrieren könnte man auch versuchen einfach die Anzahl der Stellen zu zählen, die sich unterscheiden. Wenn es geht ohne dabei eine if-Abfrage benutzen zu müssen. In Assembler könnte man beide Werte subtrahieren und anschließend das Carry auf einen Zähler draufaddieren. Außerhalb der Funktion könnte man dann prüfen, ob der return-Wert größer als Null ist. Das würde es dem Kompiler zumindest schwieriger machen da etwa rauszuoptimieren.

Das brachte mich auf eine Idee:
Ich bin mir relativ sicher, dass das Vorzeichenbit garantiert das allerlinkste ist. Wenn ich beide Subtraktionen durchführe und jeweils dieses Bit zu einem Zähler addiere, müsste er bei jedem Index, an dem sich die Bytes unterscheiden, um 1 wachsen:
Code:
size_t my_memcmp(const void *buf1, const void *buf2, size_t len) {
    size_t index, diffcnt = 0;
    const uint8_t *cbuf1 = buf1, *cbuf2 = buf2;

    for(index = 0; index < len; index++) {
        diffcnt += ((cbuf1[index] - cbuf2[index]) >> 7);
        diffcnt += ((cbuf2[index] - cbuf1[index]) >> 7);
    }

    return diffcnt;
}

Nicht getestet, könnte mich täuschen. Meinungen?
 
Wie sieht es mit folgender Funktion aus?

Code:
int cmp(const void * a, const void * b, size_t size) {
	const char * aa = a; const char * bb = b;
	int result = 0;
	size_t i;
	for(i = 0; i < size; ++i) {
		result |= aa[i] ^ bb[i];
	}
	return result;
}

Die Bytes werden bitweise per XOR verknüpft und das Ergebnis per bitweisem ODER in die Variable "result" geschrieben.
Die XOR-Operation ergibt als Ergebnisbit 0, wenn die Quellbits gleich sind und 1, wenn sie sich unterscheiden.
Die Oder-Operation fügt dem Ergebnis die Einser-Bits hinzu und entfernt niemals Bits aus dem Ergebnis.
Die Funktion gibt daher nur den Wert 0 zurück, wenn die Bytefolgen von a und b gleich sind.
 
Ack der III schrieb:
Wie sieht es mit folgender Funktion aus? [...]

Bei meinem Einfall von letzter Nacht war ich mir immer noch sehr unsicher, ob das Verhalten nicht doch noch vom Inhalt der Puffer abhängt.
Eine Subtraktion ist ja nicht zwangsläufig von allen Bits abhängig und es müssen Überträge berücksichtigt werden. :/

Deine bitweisen Operationen zwingen den Prozessor zumindest meiner laienhaften Vorstellung nach dazu, jedes Bit auch wirklich anzusehen,
es können keine Überträge auftreten und es wird bei jedem Durchlauf nur ein einziger Ausdruck abgearbeitet, was deine Lösung vermutlich
auch noch deutlich schneller macht als meine.

Dein Vorschlag gefällt mir außerordentlich gut :3 Danke dafür. Werde ihn heute Abend mal durch verschiedene Compiler schieben und gucken,
ob die es doch noch kaputt machen :x
 
Mal so ein paar dumme Fragen zu den bisherigen Codes hier: Die Anzahl der Zeichen wird hier über einen 3. Parameter übergeben. Wenn ich dem folge, müsste der 3. Parameter dann immer maximal die Anzahl der Zeichen der kleineren Zeichenkette sein, da sonst eine Zugriffsverletzung auftreten sollte, oder? Was nun, wenn die Anzahl der Zeichen sich unterscheiden aber bis auf die Länge des Kürzeren gleich sind, z.b. "Hello World!" und "Hello World! Wie geht es dir?", dann würde die Funktion doch ein positives Ergebnis zurückgeben, obwohl die Zeichenketten doch unterschiedlich sind? Oder übersehe ich da etwas? Klar könnte man die kürzere Kette auffüllen um eine gleiche Länge zu erhalten, aber wer garantiert, dass in der längeren Kette dann nicht genau die gleichen Zeichen drin sind, sodaß hier wieder ein falsch positives Ergebnis rauskommt? Nur so ein paar Anfängerfragen, die sich mir stellen...

PS: Danke, asdfman für diesen sehr interessanten Thread!
 
asdfman schrieb:
Eine Subtraktion ist ja nicht zwangsläufig von allen Bits abhängig und es müssen Überträge berücksichtigt werden. :/
Wieso sollte sie nicht von allen Bits abhängig sein? Dei Dauer einer 8Bit Integersubtraktionen ist auf allen mir bekannten Platformen unabhängig von den Zahlen, die subtrahiert werden.
 
Miuwa schrieb:
Wieso sollte sie nicht von allen Bits abhängig sein? Dei Dauer einer 8Bit Integersubtraktionen ist auf allen mir bekannten Platformen unabhängig von den Zahlen, die subtrahiert werden.

Mein Gedanke dabei war, dass wenn man bspw 1 von 2 abzieht, alle Bits von 4 an aufwärts irrelevant sind. Vor Allem gibt es nur ein Bit Übertrag. Wenn man 1 von 0 abzieht, geht der Übertrag aber die komplette Breite durch.
Die konkrete Umsetzung einer Subtraktion als elektrische Schaltung ist mir aber unbekannt. Ich lese aus deiner Bemerkung, dass meine Annahme falsch war. Eine Erklärung, wie das genau funktioniert fände ich extrem interessant.

Was nun, wenn die Anzahl der Zeichen sich unterscheiden aber bis auf die Länge des Kürzeren gleich sind, z.b. "Hello World!" und "Hello World! Wie geht es dir?"
Man muss vor dem Aufruf der Funktion die Längen vergleichen. Wenn die sich unterscheiden, muss man gar nichts mehr weiter prüfen, um zu wissen, dass die Puffer nicht identisch sind. Ein Angreifer würde daraus auch keine
Information gewinnen, weil die geforderte Länge, die in die Vergleichsfunktion geworfen wird, (zumindest in meinem Fall) vorher bekannt und konstant ist. Ich bin nun kein Experte, aber kann da auch keine Angriffsfläche sehen,
denn man erhält entweder alles oder nichts. Wenn die Länge stimmt, dauert es eine Zeitspanne, die linear von der Länge abhängt. Er gewinnt also keine Information, denn die Länge würde der Angreifer ja eh vorgeben. Stimmt
die Länge nicht, erfährt er das zwar, aber dafür ist es für ihn unmöglich, zu erfahren, welche Daten denn nun in dem fraglichen Puffer stehen, denn der Puffer wird überhaupt nicht mehr angesehen, sondern sofort verworfen. Jedes
darauf folgende Verhalten des Programms steht dann in keinem Zusammenhang mehr zu den Daten, die vom Angreifer gekommen sind.
 
Zuletzt bearbeitet:
Der "Witz" ist, dass du ja erstmal die höheren Bits "ansehen" musst, um zu sehen, dass du nur 1 von 2 abziehst. Wie die Schaltung für solche Multibit-Addierer konkretet aussieht weiß ich auch nicht, ist evtl auch von CPU zu CPU unterschiedlich. Solange die Daten aber nicht zur Compilezeit bekannt sind ist die Ausführungszeit einer "Basisinstruktion" aber immer unabhängig von den konkreten Daten. Es kann aber durchaus einen Unterschied machen, ob du einen Wert z.B. explizit mit 0 oder 1 vergleichst, weil der Compiler dann potentiell andere Prozessorinstruktionen verwendet.

Wenn du dich dafür interessierst, wie ein moderner Prozessor genau funktioniert kann ich dir folgende Links empfehlen:
http://www.lighterra.com/papers/modernmicroprocessors/
http://www.realworldtech.com/haswell-cpu/
 
Rossibaer schrieb:
Mal so ein paar dumme Fragen zu den bisherigen Codes hier

Deine Fragen sind absolut berechtigt und richtig. Im Allgemeinen gilt:

  • Die Länge für den Aufruf der Funktion muss der Länge der kleineren Bytefolge entsprechen sonst gibt es eine Zugriffsverletzung.
  • Wenn zwei unterschiedlich lange Bytefolgen bis zur Länge der kleineren Bytefolge gleich sind, gibt die Funktion, bei Übergabe der kleineren Länge als Grenze, die Gleichheit der Bytefolge aus.

Die richtige Lösung hast du schon vorgeschlagen: Die kleinere Bytefolge muss aufgefüllt werden.
Wie füllt man aber auf, ohne nicht zufällig das "richtige" aufzufüllen?

Man muss zwischen null-terminierten Zeichenketten (also Texteingaben) und Binärdaten unterscheiden.
Da Binärdaten nicht null-terminiert sind - Null kann ja durchaus ein gültiger Wert sein - muss die Länge immer bekannt sein.
Wenn man Binärdaten auf Gleichheit testen will, sind diese für gewöhnlich auch gleich lang.
Eine Hash-Funktion kann zum Beispiel aus einer beliebig langen Bytefolge einen genau 16 Bytes langen Hash-Wert berechnen.
Möchtest du zwei Hash-Werte vergleichen, so liest du exakt 16 Bytes pro Wert ein. Mehr Bytes werden ignoriert, bei weniger Bytes gibt es einen Fehler oder man liest so lange, bis man 16 Bytes bekommt.
Den Vergleich der Hash-Werte erreichst du dann über den Aufruf von memcmp().
Binärdaten muss man also gar nicht auffüllen.

Zeichenketten sind dagegen null-terminiert. Das bedeutet, dass das erste Null-Byte das Ende der Zeichenkette markiert.
Alles was dahinter liegt, wird ignoriert. Alle C-Funktionen, die auf null-terminierten Zeichenketten arbeiten,
beenden die Abarbeitung der Zeichenkette bei Vorkommen eines Null-Bytes.
Da man im Regelfall die Länge von Texteingaben nicht kennt, nutzt man zum Vergleich zweier Zeichenketten die Funktion strcmp(), welche beim ersten Null-Byte stoppt.
Zum Auffüllen lässt sich daher das Null-Byte verweden.

In der C-Standardbibliothek sieht man zum Beispiel, dass alle Funktionen, die mit "mem" beginnen einen Längenparameter haben und alle Funktionen, die mit "str" beginnen das Null-Byte als Endemarke verwenden.

Die Frage des Thread-Erstellers war ja, wie man Eingaben vergleichen kann, sodass die Vergleiche unabhängig von der Eingabe gleich lang dauern, um Timing-Attacken zu verhindern.
Eine Lösung für memcmp() scheint deutlich leichter als eine für strcmp().

Schafft man es, zwei Zeichenketten auf quasi gleiche und bekannte Längen zu bekommen, kann man die Lösung für memcmp() für den Vergleich verwenden.
Ein Beispiel wie man das macht, zeige ich weiter unten.

asdfman schrieb:
Man muss vor dem Aufruf der Funktion die Längen vergleichen. Wenn die sich unterscheiden, muss man gar nichts mehr weiter prüfen, um zu wissen, dass die Puffer nicht identisch sind.

Wenn die Eingabe eine Bytefolge ist, deren Länge bekannt ist, hat man kein Problem.
Wenn es sich um eine Zeichenfolge handelt, kann der Angreifer erfahren, aus wie vielen Zeichen die gesuchte Zeichenkette besteht.

Als Beispiel soll ein Webserver dienen, bei dem man auf den Adminbereich zugreifen kann, indem man ein Passwort eingibt.
Dieses Passwort ist 20 Zeichen lang und soll im Klartext in der Variable "geheim" gespeichert sein (Passwörter sollten natürlich nie im Klartext gespeichert sein, sondern zum Beispiel als Hash-Wert).

Code:
char * geheim = "...";
int sizeOfGeheim = sizeof geheim; // 20

char * input = inputOfClient();
int sizeOfInput = strlen(input); // Dauer in Abhängigkeit der Eingabe
if(sizeOfInput == sizeOfGeheim) {
    return cmp(geheim, input, sizeofGeheim); // Vergleichsfunktion mit konstanter Dauer
} else {
    return 1;
}

Angenommen das Verarbeiten eines Bytes benötigt eine Zeiteinheit. Dann ergibt sich folgende Tabelle:

Eingabe (Zeichen)Dauer (Zeiteinheiten)
1818
1919
2060
2121

Bei einer Eingabe von 20 Zeichen dauert die Verarbeitung viel länger, als bei den anderen Eingaben, da in diesem Fall cmp() aufgerufen wird.
Ein Angreifer erfährt also, dass das Passwort 20 Zeichen lang sein muss und kann zum Beispiel eine Wörterbuchattacke mit passenden Wörtern starten.
Durch die Verwendung von cmp() statt strcmp() wird die Timing-Attacke sogar verstärkt, da über die vollen 20 Bytes verglichen wird. strcmp() würde nach dem ersten falschen Zeichen beenden.
Der gesamte Code würde mit strcmp() zum Beispiel nur 22 Zeiteinheiten benötigen.

Eine Lösung ist folgende:

Code:
// Vergleichsfunktion aus meinem vorherigen Beitrag
int cmp(const void * a, const void * b, size_t size) {
	const char * aa = a; const char * bb = b;
	int result = 0;
	size_t i;
	for(i = 0; i < size; ++i) {
		result |= aa[i] ^ bb[i];
	}
	return result;
}

#define MAX_SIZE 100

static char password[MAX_SIZE];

void setPassword(const char * text) {
	strncpy(password, text, MAX_SIZE);
}

int testPassword(const char * text) {
	char buffer[MAX_SIZE];
	strncpy(buffer, text, MAX_SIZE);
	return cmp(password, buffer, MAX_SIZE);
}

In der Variable "password" wird das Passwort über setPassword() einmalig gesetzt.
Die maximale Länge von Passwörtern wird auf 100 Zeichen beschränkt.

Es ist sehr sinnvoll Eingaben zu beschränken. Auch Passwörter die man nur als Hash-Wert speichert, sollten in der Eingabe begrenzt sein. Vor ein paar Wochen war ein CMS in den News, welches Passwörter zwar hashte aber keine Begrenzung in der Länge vornahm. Dadurch konnte das CMS per DOS-Angriff lahmgelegt werden, indem man Passwörter mit einer Länge von 100 bis 1000 MB übergab und der Server somit mit Hashen beschäftigt war.

Über testPassword() kann dann ein beliebiges Passwort gegen das geheime Passwort getestet werden.
Warum der Code funktioniert, liegt an der Funktionsweise von strncpy().
Die Funktion schreibt immer MAX_SIZE viele Zeichen. Ist die Eingabe kürzer, füllt die Funktion den Rest mit Null-Bytes auf.
Dadurch kann cmp() über die Länge der Arrays (also MAX_SIZE) vergleichen.

ACHTUNG: Ist die Eingabe 100 Zeichen oder länger, wird der Rest zwar abgeschnitten, strncpy() setzt aber kein Null-Byte.
Dadurch sind password[] und buffer[] keine null-terminierten Zeichenketten und sollten außerhalb der zwei Funktionen nicht verwendet werden.
Der Vergleich ist aber kein Problem, da wir in cmp() über die bekannte Länge der Arrays vergleichen.
Da kein Null-Byte geschrieben wird, ist auch meine Aussage richtig, dass ein Passwort maximal 100 Zeichen lang sein kann.
 
Zuletzt bearbeitet:
Sind paar Punkte dabei an die ich bis dahin noch nicht gedacht hatte. Sehr interessant!

Letztendlich lese ich daraus, dass es besser ist Hashwerte zu vergleichen deren Längen konstant sind um somit einen möglichen Angriffsvektor über das Timing auszuschließen. Die Eingabe der Zeichenkette sollte ebenfalls begrenzt werden um einen DOS Angriff zu verhindern.

Danke Ack für die ausführlichen Erklärungen! Weiter so...

Rossibaer
 
Zurück
Oben