2019年3月24日 星期日

c++ 寫一個簡單的 https client

寫 https 的程式基本上就是將 http 的封包透過 TLS(Transport Layer Security:傳輸層安全協議)/SSL 加密後再傳出去, 收到的封包也是先經過 TLS/SSL 解密後還原.參考文章: https://wiki.openssl.org/index.php/SSL/TLS_Client
設定完 https server(以下使用 local host: 127.0.0.1 TCP port: 5000). 安裝 SSL 開發檔:
sudo apt-get install libssl–dev
編輯一個簡單的 https client 文字檔:
// client.c
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <openssl/ssl.h>
struct sessionTLS {
    int sid;
    SSL_CTX *ctx;
    SSL *ssl;
};
void freeTLS(sessionTLS &tls) {
    if (tls.ssl != NULL) SSL_free(tls.ssl);   
    if (tls.sid > 0)     close(tls.sid);
    if (tls.ctx != NULL) SSL_CTX_free(tls.ctx); 

}
void bindSSL(sessionTLS &tls) {
    tls.ssl = SSL_new(tls.ctx);
    if(tls.ssl != NULL ) {
        SSL_set_fd(tls.ssl, tls.sid);
        SSL_connect(tls.ssl);
        printf("\nsession TLS encryption: %s\n", SSL_get_cipher(tls.ssl));
        X509 * CA = SSL_get_peer_certificate(tls.ssl);

        if ( CA != NULL )  {
            char * subject= X509_NAME_oneline(X509_get_subject_name(CA), 0, 0);
            char * issuer = X509_NAME_oneline(X509_get_issuer_name(CA) , 0, 0);
            printf("CA: %s , %s\n", subject, issuer);
            free(subject);
            free(issuer);
            X509_free(CA);
        }
    }
}
sessionTLS connectIP(const char *ipaddress, int tcpPort){
    SSL_library_init();
    sessionTLS tls;// create a new TLS object
    tls.ctx = SSL_CTX_new(SSLv23_method());
    tls.sid = socket(AF_INET, SOCK_STREAM, 0);
    sockaddr_in host;
    host.sin_family = AF_INET;
    host.sin_port     = htons(tcpPort);
    inet_pton(AF_INET, ipaddress, &host.sin_addr) ;
    connect(tls.sid, (sockaddr*)&host, sizeof(host));
    bindSSL(tls);// bind tls with SSL
    return  tls;
}
int writeTLS(sessionTLS &tls, char *msg, int len) { return SSL_write(tls.ssl, msg, len); }
int  readTLS(sessionTLS &tls, char *buf, int len) { return SSL_read(tls.ssl, buf, len); }
int main() { 
    char msg[]="Hello\n";
    char buf[1024];
    sessionTLS tls = connectIP("127.0.0.1", 5000);
    writeTLS(tls, msg, strlen(msg));
    int bytes = readTLS(tls, buf, sizeof(buf));

    char *ptr = buf;
    while (bytes-- >0) printf("%c", *ptr ++);
    printf("\n");
    freeTLS(tls);
}

用 g++ 編譯並執行:
g++  client.c -lssl -lcrypto && ./a.out

沒有留言: