Превратите простой сокет в сокет SSL - PullRequest
103 голосов
/ 08 октября 2011

Я написал простые программы на C, которые используют сокеты («клиент» и «сервер»). (Использование UNIX / Linux)

Серверная сторона просто создает сокет:

sockfd = socket(AF_INET, SOCK_STREAM, 0);

А затем связывает его с sockaddr:

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

И слушает (и принимает и читает):

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

Клиент создает сокет, а затем записывает в него.

Теперь я хочу преобразовать это простое соединение в соединение SSL самым простым, самым идиллическим, изощренным и быстрым способом.

Я пытался добавить OpenSSL в свой проект, но я не могу найти простой способ реализовать то, что я хочу.

Ответы [ 4 ]

134 голосов
/ 02 мая 2013

Есть несколько шагов при использовании OpenSSL.У вас должен быть изготовлен сертификат SSL, который может содержать сертификат с закрытым ключом, и обязательно укажите точное местоположение сертификата (в этом примере он находится в корневом каталоге).Есть много хороших учебных пособий.

Некоторые из них включают:

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

Вам потребуется инициализировать OpenSSL:

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);
}

Теперь для большей части функциональности.Возможно, вы захотите добавить цикл while для соединений.

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();
}

После этого вы сможете читать или писать, используя:

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

Обновление SSL_CTX_new следуетвызываться с помощью метода TLS, который наилучшим образом соответствует вашим потребностям для поддержки более новых версий безопасности, вместо SSLv23_server_method().См .: OpenSSL SSL_CTX_новое описание

TLS_method (), TLS_server_method (), TLS_client_method (). Это универсальные версии-гибкие Методы SSL / TLS.Фактическая используемая версия протокола будет согласована с самой высокой версией, взаимно поддерживаемой клиентом и сервером.Поддерживаемые протоколы: SSLv3, TLSv1, TLSv1.1, TLSv1.2 и TLSv1.3.

16 голосов
/ 26 апреля 2013

OpenSSL довольно сложно.Легко случайно отбросить всю вашу безопасность, если не вести переговоры совершенно правильно.(Черт, меня лично укусила ошибка, когда curl неправильно читал предупреждения OpenSSL и не мог общаться с некоторыми сайтами.)

Если вы действительно хотите быстро и просто, поставьте шип перед вашей программой называйте это днем.Использование SSL в другом процессе не замедлит вас: http://vincent.bernat.im/en/blog/2011-ssl-benchmark.html

7 голосов
/ 06 ноября 2015

Для таких, как я:

Был когда-то пример в источнике SSL в каталоге demos/ssl/ с примером кода на C ++.Теперь он доступен только через историю: https://github.com/openssl/openssl/tree/691064c47fd6a7d11189df00a0d1b94d8051cbe0/demos/ssl

Вам, вероятно, придется найти рабочую версию, я первоначально опубликовал этот ответ 6 ноября 2015 года. И мне пришлось редактировать источник - не сильно.

Сертификаты: .pem в demos/certs/apps/: https://github.com/openssl/openssl/tree/master/demos/certs/apps

0 голосов
/ 08 ноября 2017

Вот мой пример ssl сокета сервера потоков (множественное соединение) 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...