Symmetrische und asymmetrische Verschlüsselung. Analyse des Algorithmus zur Übertragung verschlüsselter Daten zwischen Servern

Wenn es zwei Maschinen gibt und Sie Daten in verschlüsselter Form an die eine oder andere Seite senden möchten - eine PHP-Bibliothek, die ich vor ein paar Monaten geschrieben und gestern Abend dotiert habe - dann möchte ich das teilen.

Nehmen wir an, eine Maschine, die verschlüsselte Daten überträgt, ist immer Maschine A, und eine Maschine, die diese Daten empfängt, hat das Symbol B. Die

Bibliothek löst zwei mögliche Fälle (falls erforderlich, füge ich Funktionen hinzu):

1) Der Fall, wenn es eine Maschine gibt (B), Dies erfordert Daten von Computer A (zum Beispiel, um einen Client-Push zu erhalten) und diese Daten müssen sicher empfangen werden. Das heißt Der Initiator der Übertragung ist Maschine B.
2) Der Fall, dass ein Computer vorhanden ist und verschlüsselte Daten auf einen anderen Computer übertragen werden müssen (B). In diesem Fall ist der Initiator der Übertragung die erste Maschine (A).

Die Bibliothek implementiert beide, für jedes von denen gibt es eine Demo:

Im ersten Fall im Ordner server_b_1 ein Skript testGetDataFromA.php
Für den zweiten Fall in einem Ordner server_a_1 ein Skript testPushDataToB.php

Die Bibliothek ist für beide Fälle dieselbe Encode.php, aber für den ersten Fall sind zusätzliche Skripte erforderlich, für den zweiten Fall andere. Um Verwirrung zu vermeiden, habe ich sie funktional in die Ordner server_a_1 und server_b_1 unterteilt (möglicherweise haben nachfolgende Versionen der Bibliothek eine andere Struktur). Wenn also beide Maschinen die Implementierung des ersten und des zweiten Verteilergetriebes erfordern, verfügt jede solche Maschine über beide Ordner.

Nun zur Implementierung beider Lösungen:

In beiden Fällen müssen die Computer einen symmetrischen Schlüssel austauschen, um verschlüsselten Text zu übertragen. Für diesen Austausch wird eine asymmetrische Verschlüsselung verwendet, nämlich einer der Rechner (X) erzeugt ein Schlüsselpaar (öffentlich und privat) und überträgt den öffentlichen Schlüssel auf den zweiten Rechner. Der zweite Computer generiert mit diesem öffentlichen Schlüssel einen symmetrischen Schlüssel und gibt den ersten zurück, der ihn mit seinem privaten Schlüssel entschlüsselt. Der Unterschied besteht darin, wer der Initiator der Übertragung ist - für den Fall, dass der verschlüsselte Text eine Abfolge von Aktionen empfangen muss, für die Übertragung - eine andere. Die betrachtete Bibliothek führt auch zusätzliche Prüfungen durch, die darauf hinauslaufen, dass Daten zusammen mit dem symmetrischen Schlüssel übertragen werden, der mit dem öffentlichen Schlüssel des symmetrischen Schlüssels verschlüsselt ist.

Bevor ich mit dem Parsing der Implementierung beginne, möchte ich nur darauf hinweisen, dass die Verschlüsselung des symmetrischen Schlüssels mit PHP-Mcrypt-Verschlüsselungsfunktionen nach folgendem Schema erfolgt:

$encrypted_data = urlencode(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $sinc_key, $notice_text, MCRYPT_MODE_ECB)));
$test_decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256,$sinc_key, base64_decode(urldecode($encrypted_data)),MCRYPT_MODE_ECB));

Die Arbeit mit asymmetrischer Verschlüsselung erfolgt mit PHP OpenSSL.

Deshalb:

Ich werde zunächst vereinfachte Schemata der beiden Übertragungsfälle betrachten, die zu Beginn angegeben wurden, und dann detaillierter.

1) Der Fall, dass es eine Maschine (B) gibt, die Daten von Maschine A benötigt (zum Beispiel muss sie einen Client-Push empfangen), und diese Daten müssen sicher empfangen werden. Das heißt Der Initiator der Übertragung ist Maschine B.

Ein vereinfachter Algorithmus für eine solche Übertragung lautet wie folgt:

Maschine B generiert ein Schlüsselpaar (privat und öffentlich) und sendet eine Anforderung an Maschine A, wobei der öffentliche Schlüssel gesendet wird (privat gelassen wird). Maschine A generiert einen symmetrischen Schlüssel, verschlüsselt die für die Übertragung erforderlichen geheimen Informationen N. Danach gibt Maschine A den mit dem öffentlichen Schlüssel verschlüsselten symmetrischen Schlüssel sowie die mit dem symmetrischen Schlüssel N verschlüsselten geheimen Informationen zurück. In den entschlüsselten Daten erhält er den symmetrischen Schlüssel und die von ihm verschlüsselten Daten. Mit einem symmetrischen Schlüssel werden geheime Daten entschlüsselt.

Es gibt keine Garantie, dass Maschine A genau unsere Maschine ist und nicht Anatols FSB-Offizier. Daher wird die Implementierung dieses Algorithmus durch die Bibliothek durch eine

Unterprüfung geringfügig geändert: (Skriptdemo - server_b_1 / testGetDataFromA.php)

Der geheime Schlüssel SIGNATURE_KEY ist auf beiden Rechnern registriert, was zu einer zusätzlichen Überprüfung führt. Maschine B generiert ein Schlüsselpaar (privat und öffentlich), den Schlüssel der aktuellen Verbindung, und sendet eine Anforderung (http: //.../server_a_1/getDataToB.php) an Maschine A, wobei der Schlüssel der aktuellen Verbindung und der öffentliche Schlüssel gesendet werden (privat bleiben). Maschine A erzeugt einen symmetrischen Schlüssel, verschlüsselt die zur Übertragung erforderlichen geheimen Informationen N. Außerdem werden zusätzliche Daten M erzeugt, die md5 aus der Zeile sind, die SIGNATURE_KEY und den aktuellen Verbindungsschlüssel enthält. Danach gibt Maschine A eine mit einem öffentlichen Schlüssel verschlüsselte Zeichenfolge aus einem symmetrischen Schlüssel und zusätzlichen Daten M sowie mit einem symmetrischen Schlüssel N verschlüsselte geheime Informationen zurück. Maschine B entschlüsselt die Daten mit einem symmetrischen Schlüssel und erzeugt eine Zeichenfolge. subject M (da md5 möglicherweise aus einer Zeichenfolge berechnet wird, die SIGNATURE_KEY und den aktuellen Verbindungsschlüssel enthält). Wenn die zusätzlichen Daten übereinstimmen (dies ist nur eine zusätzliche Prüfung für jede Transaktion, die Maschine A mit SIGNATURE_KEY und daher mit unserer Maschine kennt), extrahiert Maschine B einen symmetrischen Schlüssel, mit dem sie die geheimen Informationen N entschlüsselt.

2) Der Fall, dass ein Computer vorhanden ist und verschlüsselte Daten auf einen anderen Computer übertragen werden müssen (B). In diesem Fall ist der Initiator der Übertragung die erste Maschine (A).

Ein vereinfachter Algorithmus für eine solche Übertragung lautet wie folgt:

Vor der Übertragung zu Maschine B benötigt Maschine A einen öffentlichen Schlüssel von Maschine B, um Informationen zu übertragen. Dazu fordert sie (Maschine A) zuerst einen öffentlichen Schlüssel von Maschine B an. Nach dem Empfang generiert Maschine A einen symmetrischen Schlüssel, verschlüsselt die erforderlichen Informationen damit und verschlüsselt ihn mit dem empfangenen öffentlichen Schlüssel. Die Daten werden an Maschine B übertragen, die das Paket mit ihrem privaten Schlüssel entschlüsselt und die Daten mit einem symmetrischen Schlüssel entschlüsselt.

Es gibt keine Garantie dafür, dass wir den öffentlichen Schlüssel von Wagen B und nicht vom FSB-Offizier Petrov erhalten haben. Daher wird die Implementierung dieses Algorithmus durch die Bibliothek durch zusätzliche Überprüfungen leicht modifiziert:

(Skriptdemo - server_a_1 / testPushDataToB.php)

Der geheime Schlüssel SIGNATURE_KEY ist auf beiden Rechnern registriert, was zu einer zusätzlichen Überprüfung führt. Maschine A generiert md5 aus dem aktuellen Verbindungsschlüssel und SIGNATURE_KEY sendet diese Daten (zusammen mit dem unverschlüsselten Schlüssel der aktuellen Verbindung) an Maschine B (http: //.../server_b_1/get_public_key.php), die nur dann einen öffentlichen Schlüssel generiert, wenn sich herausstellt, dass dies der Fall ist das gleiche md5 aus seinem SIGNATURE_KEY und dem empfangenen Schlüssel der aktuellen Verbindung. Dies löst nicht das Problem, dass der öffentliche Schlüssel genau von Maschine A und nicht von der Maschine des FSB-Beauftragten Vasily empfangen wird, sondern garantiert Maschine B, dass sie einen öffentlichen Schlüssel speziell für Maschine A generiert (obwohl das Generieren eines öffentlichen Schlüssels im Allgemeinen willkürlich ist, aber Auch hier ist es besser, auf Nummer sicher zu gehen. Md5 wird zusammen mit dem öffentlichen Schlüssel aus SIGNATURE_KEY und dem zweiten Schlüssel der aktuellen Verbindung generiert. Der zweite Schlüssel der aktuellen Verbindung ist ein beliebiger Hash. Die Daten des öffentlichen Schlüssels, des zweiten Schlüssels der willkürlichen Verbindung und des angegebenen md5 werden an Maschine A zurückgegeben. Nachdem Maschine A den zweiten Schlüssel der willkürlichen Verbindung empfangen hat, generiert sie in Kenntnis von SIGNATURE_KEY eine Verifikation md5, und wenn sie mit der empfangenen Maschine übereinstimmt, wird der öffentliche Schlüssel von Maschine B nicht berücksichtigt von Wassili.

Ferner erzeugt Maschine A (hier ähnelt die Schaltung bereits dem ersten Fall der Datenübertragung) einen symmetrischen Schlüssel und eine zusätzliche Prüfung, die aus SIGNATURE_KEY und dem Schlüssel für die aktuelle Verbindung md5 ist. Diese Daten werden mit dem öffentlichen Schlüssel von Computer B verschlüsselt. Anschließend werden die Daten zusammen mit dem Schlüssel der aktuellen Verbindung an Computer B (http: //.../server_b_1/pushDataFromA.php) gesendet, der den aktuellen Verbindungsschlüssel und SIGNATURE_KEY md5 basierend auf den aus diesen Daten erhaltenen Daten generiert , prüft gegen den empfangenen, was garantiert, dass die Daten nicht vom FSB-Offizier von Nikolai stammen. Wenn alles in Ordnung ist und die Prüfung bestanden ist, wird mit Hilfe des privaten Schlüssels ein symmetrischer Schlüssel extrahiert, mit dem die Nachricht bereits entschlüsselt ist.

Ich würde mich freuen, wenn diese Informationen jemandem nützlich sind.

Code auf dem Git (es gibt eine Demo)

Jetzt auch beliebt: