Betrachten Sie den folgenden Aufruf von RSA_generate_key()
:
Das Generieren eines 8.192-Bit-RSA-Schlüssels kann sehr lange dauern (von wenigen Sekunden bis zu einigen Minuten). Angenommen, die Anwendung, die die obige Codezeile enthält, bietet dem Benutzer eine Schaltfläche, die die Schlüsselgenerierung abbricht.
Wie kann ich die Berechnung abbrechen und die Funktion zurückgeben, bevor der Schlüssel generiert wurde? Ich erinnere mich, dass das dritte Argument von RSA_generate_key()
eine Callback-Funktion ist, die zum Anzeigen des Fortschritts verwendet wird - Gibt es irgendeine Möglichkeit, dass Callback einen Wert zurückgeben könnte, der "Operation abbrechen und zurückgeben" bedeutet?
Das Ausführen der Funktion in einem anderen Thread und das Beenden des Threads ist keine Option.
Da RSA_generate_key
einen Fortschrittsrückruf bereitstellt, können Sie longjmp
daraus entfernen, um die Funktion zu beenden. Mit etwas zusätzlichem Code können Sie einen Wrapper für RSA_generate_key
erstellen, der eine generische Testfunktion akzeptiert, mit der nach einem Timeout oder einem vom Windowing-System gesetzten Flag gesucht werden kann.
Dieser Ansatz ist überraschend portabel, da longjmp
sowohl von C89 als auch von C99 gefordert wird. Sein Nachteil ist, dass Ressourcen verloren gehen können, wenn die Funktion, für die Sie Longjping durchführen, diese dynamisch zuweist. In der Praxis kann das Leck jedoch klein genug sein, um unbemerkbar zu sein, wenn es selten oder nur auf ausdrückliche Benutzeranfrage erfolgt. Um sicher zu sein, dass dies der Fall ist, führen Sie den Code in einer engen Schleife aus und beobachten Sie den Ressourcenverbrauch des Prozesses.
Hier ist ein Testprogramm für die obige Funktion:
%Vor% Das Testprogramm geht von POSIX gettimeofday
aus, kann aber trivialerweise in eine andere hochauflösende Uhr umgewandelt werden, wie sie vom System bereitgestellt wird. Testverfahren ist wie folgt:
Hängen Sie beide Code-Teile an eine Datei an und kompilieren Sie sie mit -lrsa
. Das Testprogramm generiert einen 4096-Bit-RSA-Schlüssel innerhalb des in Millisekunden angegebenen Zeitlimits in der Befehlszeile. In allen Fällen wird der resultierende Zeiger RSA *
gedruckt, um anzuzeigen, ob my_generate_key
die Anforderung abgeschlossen hat oder abgebrochen wurde. Die Ausgabe von time
begleitet die Ausführung als Plausibilitätsprüfung, um zu überprüfen, ob das Zeitlimit eingehalten wird:
Der Fortschrittsrückruf kann nicht zum Abbrechen der Funktion verwendet werden, sondern dient lediglich dazu, den Fortschritt für den Benutzer anzuzeigen. ( Lesen Sie hier mehr )
Erzeuge einen Thread, um RSA_generate_key()
aufzurufen, damit er im Hintergrund ausgeführt wird. Wenn der Benutzer die Abbrechen-Schaltfläche drückt, kill den Thread.
Ich glaube, das Problem besteht darin, dass ein Callback Ihnen normalerweise nicht die Möglichkeit gibt, Informationen in zu senden, sondern nur Informationen zurück . Wie einige der anderen Poster erwähnt haben, könnten Sie in Betracht ziehen, den Quellcode der eigentlichen Schlüsselgenerierungsroutine zu ändern und Ihre eigene Version zu kompilieren. In diesem Fall könnten Sie eine Art von Wert durch Referenz zurück an Ihre aufrufende Routine übergeben, die Sie dann außerhalb setzen könnten, und somit eine Fehlerbedingung auslösen.
Hinweis : RSA_generate_key
ist eigentlich veraltet und ist jetzt einfach ein Wrapper für RSA_generate_key_ex
.
Laut Version 1.19.4.2 von Die Datei rsa_gen.c
, es sei denn, Sie befinden sich in FIPS_mode
. Der Schlüssel wird von der statischen Methode rsa_builtin_keygen
generiert. In FIPS_mode
wird es erzeugt durch was auch immer rsa->meth->rsa_keygen
ist, wenn Sie RSA_generate_key
eingeben.
Das heißt, es gibt eine Reihe von Stellen, an denen der Callback ( cb
-Parameter) an andere Methoden weitergegeben wird, vermutlich damit diese Methoden ihn zum Aktualisieren des Status aufrufen können.
Der Trick wäre, entweder BN_GENCB
zu aktualisieren, um eine Art "cancel" -Flag zu enthalten, oder die Art und Weise zu ändern, in der der Callback innerhalb der Methode aufgerufen wird. Wenn die Callback-Methode ausgelöst wird, können Sie festlegen eine Flagge, die die aufrufende Funktion würdigen würde, indem sie das Generations-Unterprogramm unterbricht.
Wie Sie vorgehen würden, ist immer noch etwas, das Sie herausfinden und durcharbeiten müssen - aber das wird Ihnen hoffentlich einen Anfang geben.
Obwohl ich niemals mit einer solchen Situation konfrontiert bin und noch nie zuvor etwas getan habe. Sie können Folgendes versuchen, wenn Sie den Quellcode von OpenSSL ändern können:
Nehmen wir an, eine Variable V wird von zwei Funktionen gemeinsam genutzt. Entweder ist es eine globale Variable oder eine statische Variable in der Datei und wird von RSA_generate_key verwendet und sagt eine andere Funktion RSA_set_V.
RSA_generate_key liest nur die Variable. RSA_set_V setzt die Variable.
In RSA_generate_key kann die zeitaufwendige Schleife eine zusätzliche Bedingung zum Überprüfen dieser Variablen verwenden. Es kann diese Schleife beenden oder die Funktion auf einen bestimmten Wert von V verlassen. z.B.
%Vor%Setzen Sie in RSA_set_V jetzt V auf CERTAIN_VALUE. Wenn der Benutzer auf Stopp klickt, rufen Sie RSA_set_V auf. Es sollte RSA_generate_key stoppen.
Es hat jedoch einige Probleme. Es kann RSA_generate_key verlangsamen.
Nach Quellcode , ohne den Code von openssl zu ändern, können wir die RSA_generate_key-Methode nicht unterbrechen, damit sie zurückkommt.
>Ich habe mir zwei Möglichkeiten ausgedacht:
Lassen Sie die Methode im Hintergrundthread laufen, und wenn der Benutzer die Abbrechen-Schaltfläche drückt, lassen Sie die Methode im Hintergrund enden. und lass den Faden danach sterben. und ignoriere die Ergebnisse. und einen neuen Thread starten, wenn der Benutzer eine andere Generation anfordert.
Ein anderer ist es, einen Unterprozess zu starten, um den Schlüssel zu generieren. Die RSA-Struktur enthält viele BIGNUM-Member, die auch Struktur einiger Ints / Ulongs sind. Nachdem der Unterprozess die Schlüssel generiert hat, kopieren Sie diese relevanten Mitglieder zurück in den übergeordneten Prozess. Wenn der Benutzer die Abbrechen-Schaltfläche drückt, ist der Unterprozess sicher. Aber nicht sicher, ob das Kopieren dieser Ints / Longs für Ihr Senario ausreicht.
Tags und Links openssl