web-dev-qa-db-de.com

Verwandeln Sie einen einfachen Socket in einen SSL-Socket

Ich habe einfache C-Programme geschrieben, die Sockets verwenden ("Client" und "Server"). (UNIX/Linux-Nutzung)

Die Serverseite erstellt einfach einen Socket:

sockfd = socket(AF_INET, SOCK_STREAM, 0);

Und bindet es dann an sockaddr:

bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));

Und hört zu (und akzeptiert und liest):

listen(sockfd,5);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
read(newsockfd,buffer,255);

Der Client erstellt den Socket und schreibt darauf.

Jetzt möchte ich diese einfache Verbindung auf einfachste, idyllischste, sauberste und schnellste Weise in eine SSL-Verbindung umwandeln.

Ich habe versucht, meinem Projekt OpenSSL hinzuzufügen, finde aber keinen einfachen Weg, um das zu implementieren, was ich will.

104
David Mape

Bei der Verwendung von OpenSSL gibt es mehrere Schritte. Sie müssen ein SSL-Zertifikat erstellen lassen, das das Zertifikat mit dem privaten Schlüssel enthalten kann. Geben Sie dabei unbedingt den genauen Speicherort des Zertifikats an (in diesem Beispiel befindet sich das Zertifikat im Stammverzeichnis). Es gibt viele gute Tutorials.

Einige beinhalten:

#include <openssl/applink.c>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

Sie müssen OpenSSL initialisieren:

void InitializeSSL()
{
    SSL_load_error_strings();
    SSL_library_init();
    OpenSSL_add_all_algorithms();
}

void DestroySSL()
{
    ERR_free_strings();
    EVP_cleanup();
}

void ShutdownSSL()
{
    SSL_shutdown(cSSL);
    SSL_free(cSSL);
}

Nun zum Großteil der Funktionalität. Möglicherweise möchten Sie eine while-Schleife für Verbindungen hinzufügen.

int sockfd, newsockfd;
SSL_CTX *sslctx;
SSL *cSSL;

InitializeSSL();
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd< 0)
{
    //Log and Error
    return;
}
struct sockaddr_in saiServerAddress;
bzero((char *) &saiServerAddress, sizeof(saiServerAddress));
saiServerAddress.sin_family = AF_INET;
saiServerAddress.sin_addr.s_addr = serv_addr;
saiServerAddress.sin_port = htons(aPortNumber);

bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));

listen(sockfd,5);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);

sslctx = SSL_CTX_new( SSLv23_server_method());
SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_DH_USE);
int use_cert = SSL_CTX_use_certificate_file(sslctx, "/serverCertificate.pem" , SSL_FILETYPE_PEM);

int use_prv = SSL_CTX_use_PrivateKey_file(sslctx, "/serverCertificate.pem", SSL_FILETYPE_PEM);

cSSL = SSL_new(sslctx);
SSL_set_fd(cSSL, newsockfd );
//Here is the SSL Accept portion.  Now all reads and writes must use SSL
ssl_err = SSL_accept(cSSL);
if(ssl_err <= 0)
{
    //Error occurred, log and close down ssl
    ShutdownSSL();
}

Sie können dann lesen oder schreiben mit:

SSL_read(cSSL, (char *)charBuffer, nBytesToRead);
SSL_write(cSSL, "Hi :3\n", 6);

Update Der SSL_CTX_new Sollte mit der TLS-Methode aufgerufen werden, die Ihren Anforderungen am besten entspricht, um die neueren Sicherheitsversionen zu unterstützen SSLv23_server_method(). Siehe: OpenSSL SSL_CTX_new description

TLS_method (), TLS_server_method (), TLS_client_method (). Dies sind die Allzweckmethoden version-flexible SSL/TLS. Die tatsächlich verwendete Protokollversion wird mit der höchsten Version ausgehandelt, die vom Client und vom Server gemeinsam unterstützt wird. Die unterstützten Protokolle sind SSLv3, TLSv1, TLSv1.1, TLSv1.2 und TLSv1.3.

135
CaptainBli

OpenSSL ist ziemlich schwierig. Es ist leicht, versehentlich Ihre gesamte Sicherheit zu verlieren, wenn Sie nicht genau richtig verhandeln. (Heck, ich bin persönlich von einem Bug gebissen worden, bei dem Curl die OpenSSL-Warnungen nicht genau richtig gelesen hat und mit einigen Sites nicht sprechen konnte.)

Wenn Sie wirklich schnell und einfach wollen, stellen Sie stud vor Ihr Programm und rufen Sie es täglich auf. Wenn Sie SSL in einem anderen Prozess verwenden, werden Sie nicht langsamer: http://vincent.bernat.im/en/blog/2011-ssl-benchmark.html

16

Für andere wie mich:

Es gab einmal ein Beispiel in der SSL-Quelle im Verzeichnis demos/ssl/ mit Beispielcode in C++. Jetzt ist es nur über den Verlauf verfügbar: https://github.com/openssl/openssl/tree/691064c47fd6a7d11189df00a0d1b94d8051cbe0/demos/ssl

Sie werden wahrscheinlich eine funktionierende Version finden müssen. Ich habe diese Antwort ursprünglich am 6. November 2015 gepostet. Und ich musste die Quelle bearbeiten - nicht viel.

Zertifikate: .pem in demos/certs/apps/: https://github.com/openssl/openssl/tree/master/demos/certs/apps

Hier mein Beispiel SSL-Socket-Server-Threads (mehrere Verbindungen) https://github.com/breakermind/CppLinux/blob/master/QtSslServerThreads/breakermindsslserver.cpp

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include <iostream>

#include <breakermindsslserver.h>

using namespace std;

int main(int argc, char *argv[])
{
    BreakermindSslServer boom;
    boom.Start(123,"/home/user/c++/qt/BreakermindServer/certificate.crt", "/home/user/c++/qt/BreakermindServer/private.key");
    return 0;
}
0
Fanex