2011年12月28日 星期三

OPENSSL-TCP SSL初心者之路


最近因為工作的關係,碰到一些加解密的問題,所以藉由這個機會,好好的回頭看了openssl這個只有編過但完全沒用過的library,還好有網友把整個openssl剖析的很透徹, 在學習的過程中幾乎沒碰到太多的問題,因為openssl每組API的使用方式實在太固定了,所以md5 api試過後,後面的數位簽章和RSA都不會太困難,而在openssl裡,SSL framework是我覺得包裝相當漂亮的函式,所以下面的內容都著重在TCP SSL的使用介紹
使用http ssl基本上有幾個流程
1. Initial socket
2. Connect socket
3. Initial SSL
    <1>SSL_library_init:initial SSL library
    <2>SSL_CTX_new:create a new SSL_CTX object to enable SSL connection
    <3>SSL_new: create SSL data stucture
    <4>SSL_set_fd:bind ssl and socket fd
    <5>SSL_connect:connect to server
4. ssl_read or ssl_write: read ssl information


底下有個範例程式,簡單的展示SSL大致的架構,但我沒加上client驗server certificate這一段,有興趣的朋友可以參考此篇文章試試看

#include <openssl/crypto.h>
#include <openssl/ssl.h>
#include <openssl/ssl23.h>
#include <openssl/ssl2.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
 
#define GETMSG "GET https://192.168.15.3/sslok.htm\r\nHost:localhost\r\nUser-Agent:Joey\r\nAccept:text/html\r\nAccept-Language:en-us,zh-tw \r\nKeep-Alive:300"
//for demo purpose, it is not a good declaration
SSL_CTX *ctx; SSL *ssl; int fd;
 
void bug(char *string) { printf("error:%s\n",string); exit(0); }
 
void *readSSLSocket(void *arg) { fd_set fds; int ret; char buf[1400]; int len;
 
FD_ZERO(&fds); FD_SET(fd, &fds); ret=select(fd + 1, &fds, NULL, NULL, NULL); if (ret>0) { ret=SSL_read(ssl, buf, 1400); printf("client receive:\n %s",buf); } }
 
void destroySSL(SSL *ssl,SSL_CTX *ctx) { SSL_set_shutdown(ssl, 2); SSL_shutdown(ssl); SSL_free(ssl); if(ctx) SSL_CTX_free(ctx); }
 
int main(int argc,char *argv[]) {
 
struct sockaddr_in srv; pthread_t mythread; char buf[1024];
 
memset(&srv,0,sizeof(srv)); srv.sin_addr.s_addr=inet_addr("192.168.15.3"); srv.sin_family=AF_INET; srv.sin_port=htons(443); fd=socket(AF_INET, SOCK_STREAM, 0); if (fd<0) bug("fd");
 
if (connect(fd,(struct sockaddr *)&srv,sizeof(srv))==-1) bug("connect");
 
SSL_load_error_strings(); if(SSL_library_init() != 1) bug("SSL_library_init"); ctx = SSL_CTX_new(SSLv3_method()); if (ctx==NULL) bug("ctx"); ssl=SSL_new(ctx); if (ssl==NULL) return; SSL_set_fd(ssl,fd); if (SSL_connect(ssl)) printf("SSL connect OK\n"); pthread_create(&mythread,NULL,readSSLSocket,NULL); pthread_detach(mythread); sleep(1); strcpy(buf,GETMSG); SSL_write(ssl, (char *)buf,1024); sleep(2); destroySSL(ssl,ctx); return 0;
 
}

沒有留言: