2016-12-19 59 views
0

私は、HTTPサーバーへの接続を作成し、そのWebサイトのコンテンツをコンソールに表示できるスクリプトを作成しました。 非常に簡単です。OpenSSLをC++ソケット接続(HTTPSクライアント)

しかし、私はhttpsサーバーに接続し、同じ手順を実行したいです。 Googleで検索したところ、検索したものは見つかりませんでした。

私を助け、私にopensslライブラリを使用できるチュートリアルを教えてください。

私は自分自身をopensslライブラリで試しましたが、ライブラリは非常に複雑で理解しづらいものです。ここで

は、HTTPクライアントの私のコードです:ここでは

#include <iostream> 
#include <ctype.h> 
#include <cstring> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netdb.h> 
#include <netinet/in.h> 
#include <unistd.h> 
#include <sstream> 
#include <fstream> 
#include <string> 
#include <arpa/inet.h> 
#include <openssl/ssl.h> 

using namespace std; 

int sock; 
struct sockaddr_in client; 
int PORT = 80; 

int main(int argc, char const *argv[]) 
{ 
    bzero(&client, sizeof(client)); 
    client.sin_family = AF_INET; 
    client.sin_port = htons(PORT); 
    client.sin_addr.s_addr = inet_addr("172.16.0.6"); 

    sock = socket(AF_INET, SOCK_STREAM, 0); 

    if (sock < 0) { 
     cout << "Error creating socket." << endl; 
     exit(1); 
    } 

    if (connect(sock, (struct sockaddr *)&client, sizeof(client)) < 0) { 
     close(sock); 
     cout << "Could not connect" << endl; 
     exit(1); 
    } 

    stringstream ss; 
    ss << "GET /" << "\r\n" 
    << "Host: 172.16.1.4\r\n" 
    << "Accept: application/json\r\n" 
    << "Connection: close" 
    << "\r\n\r\n"; 
    string request = ss.str(); 

    if (send(sock, request.c_str(), request.length(), 0) != (int)request.length()) { 
     cout << "Error sending request." << endl; 
     exit(1); 
    } 

    char cur; 
    while (read(sock, &cur, 1) > 0) { 
     cout << cur; 
    } 

    return 0; 
} 
+3

はい、OpenSSLライブラリは、複雑さと使いにくさの点で平均以上です。どのように使用するかを理解するだけでなく、SSL/TLSの背後にあるテクノロジーについての実用的な知識も必要です。そのドキュメンテーションを読み始めます。 SSLアプリケーションの実装に関する書籍を入手し、その本の読書を開始してください。いいえ、ショートカットがなく、魔法の杖を放棄することはできません。また、SSLクライアントを空中から飛び出させることもできます。ライブラリの使用方法の学習や学習に多大な時間と労力を費やすことに代わる方法はありません。 –

+0

ええ、私は知っています。 TLS/SSLの知識が少しあります。しかし、私はC + +プログラムのための "高速"ソリューションが必要です。今私は良い方法を見つけました:私はlibcurlライブラリを使います。ここにはすでにHTTPS実装があります。どうもありがとうございました! – Hball

+0

OpenSSLを使うと、最も単純なアプローチは 'connect()'、 'read()'、 'send()'をそれぞれ 'ssl_connect()'、 'ssl_read()'、 'ssl_write()'に置き換えることです。これは、HTTPとHTTPSが異なるコードパスを使用するため、既存のソケットロジックを書き直すことを意味します。既存のソケットコードを再利用し、その上にOpenSSLを追加したい場合は、OpenSSLの 'BIO' APIを使用して、' connect() '、' read() 'および' send() 'を引き続き使用できます。暗号化されたデータを前後に処理する専用のメモリバッファをいくつか関連付けるだけです。見て回ると**トン**の例があります。 –

答えて

1

https://google.ruに接続し、プリントがページをダウンロードしたサンプルSSLクライアントです:SSLClient.cpp

//============================================================================ 
// Name  : SSLClient.cpp 
// Compiling : g++ -c -o SSLClient.o SSLClient.cpp 
       g++ -o SSLClient SSLClient.o -lssl -lcrypto 
//============================================================================ 
#include <stdio.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <openssl/ssl.h> 
#include <openssl/err.h> 
using namespace std; 

SSL *ssl; 
int sock; 

int RecvPacket() 
{ 
    int len=100; 
    char buf[1000000]; 
    do { 
     len=SSL_read(ssl, buf, 100); 
     buf[len]=0; 
     printf(buf); 
    } while (len > 0); 
    if (len < 0) { 
     int err = SSL_get_error(ssl, len); 
     if (err == SSL_ERROR_WANT_READ) 
      return 0; 
     if (err == SSL_ERROR_WANT_WRITE) 
      return 0; 
     if (err == SSL_ERROR_ZERO_RETURN || err == SSL_ERROR_SYSCALL || err == SSL_ERROR_SSL) 
      return -1; 
    } 
} 

int SendPacket(const char *buf) 
{ 
    int len = SSL_write(ssl, buf, strlen(buf)); 
    if (len < 0) { 
     int err = SSL_get_error(ssl, len); 
     switch (err) { 
     case SSL_ERROR_WANT_WRITE: 
      return 0; 
     case SSL_ERROR_WANT_READ: 
      return 0; 
     case SSL_ERROR_ZERO_RETURN: 
     case SSL_ERROR_SYSCALL: 
     case SSL_ERROR_SSL: 
     default: 
      return -1; 
     } 
    } 
} 


void log_ssl() 
{ 
    int err; 
    while (err = ERR_get_error()) { 
     char *str = ERR_error_string(err, 0); 
     if (!str) 
      return; 
     printf(str); 
     printf("\n"); 
     fflush(stdout); 
    } 
} 


int main(int argc, char *argv[]) 
{ 
    int s; 
    s = socket(AF_INET, SOCK_STREAM, 0); 
    if (!s) { 
     printf("Error creating socket.\n"); 
     return -1; 
    } 
    struct sockaddr_in sa; 
    memset (&sa, 0, sizeof(sa)); 
    sa.sin_family  = AF_INET; 
    sa.sin_addr.s_addr = inet_addr("74.125.232.247"); // address of google.ru 
    sa.sin_port  = htons (443); 
    socklen_t socklen = sizeof(sa); 
    if (connect(s, (struct sockaddr *)&sa, socklen)) { 
     printf("Error connecting to server.\n"); 
     return -1; 
    } 
    SSL_library_init(); 
    SSLeay_add_ssl_algorithms(); 
    SSL_load_error_strings(); 
    const SSL_METHOD *meth = TLSv1_2_client_method(); 
    SSL_CTX *ctx = SSL_CTX_new (meth); 
    ssl = SSL_new (ctx); 
    if (!ssl) { 
     printf("Error creating SSL.\n"); 
     log_ssl(); 
     return -1; 
    } 
    sock = SSL_get_fd(ssl); 
    SSL_set_fd(ssl, s); 
    int err = SSL_connect(ssl); 
    if (err <= 0) { 
     printf("Error creating SSL connection. err=%x\n", err); 
     log_ssl(); 
     fflush(stdout); 
     return -1; 
    } 
    printf ("SSL connection using %s\n", SSL_get_cipher (ssl)); 

    char *request = "GET https://www.google.ru/intl/en/about/company/facts/ HTTP/1.1\r\n\r\n"; 
    SendPacket(request); 
    RecvPacket(); 
    return 0; 
} 

注意あなたがしたい場合は、そのopensslを使用してクライアントとサーバー間でデータを交換するには、ドキュメンテーションの説明に従って、エラーコードSSL_ERROR_WANT_READおよびSSL_ERROR_WANT_WRITEを処理する必要があります。しかし、ここではHTTPSプロトコルはシリアルでは必要ありません。

関連する問題