OpenSSL是爲網絡通信提供安全及數據完整性的一種安全協議,囊括了主要的密碼算法、常用的密鑰和證書封裝管理功能以及SSL協議,並提供了豐富的應用程序供測試或其它目的使用。SSL是Secure Socket Layer(安全套接層協議)的縮寫,可以在Internet上提供祕密性傳輸。SSL協議要求建立在可靠的傳輸層協議(TCP)之上。SSL協議的優勢在於它是與應用層協議獨立無關的,高層的應用層協議(例如:HTTP,FTP,TELNET等)能透明地建立於SSL協議之上。SSL協議在應用層協議通信之前就已經完成加密算法、通信密鑰的協商及服務器認證工作。在此之後應用層協議所傳送的數據都會被加密,從而保證通信的私密性。
服務器端OpenSSL編程流程:
1.SSL庫初始化:SSL_library_init();
2.加載SSL算法:OpenSSL_add_all_altorithms();
3.加載錯誤信息:SSL_load_error_strings();
4.創建會話環境:SSL_CTX_new();
5.加載用戶證書:SSL_CTX_use_certificate_file();
6.加載用戶私鑰:SSL_CTX_PrivateKey_file();
7.檢查用戶證書私鑰是否匹配:SSL_CTX_check_private_key();
8.創建socket();
9.bind(sockfd);
10.listen(sockfd,maxconnect);
11.accept(sockfd,...);
12.創建新的ssl:SSL_new();
13.accetpfd
14.建立ssl連接:ssl_accept
15.SSL_read();
16.SSL_write();
17.SSL_shutdown(),SSL_free(),SSL_CTX_free();
客戶端OpenSSL編程流程:
1.SSL庫初始化:SSL_library_init();
2.加載SSL算法:OpenSSL_add_all_altorithms();
3.加載錯誤信息:SSL_load_error_strings();
4.創建會話環境:SSL_CTX_new();
5.加載用戶證書:SSL_CTX_use_certificate_file();
6.加載用戶私鑰:SSL_CTX_PrivateKey_file();
7.檢查用戶證書私鑰是否匹配:SSL_CTX_check_private_key();
8.創建socket();
9.connect();
10.創建新的ssl:SSL_new();
11.加入ssl,SSL_set_fd
12.創建SSL_connect();
13.SSL_write();
14.SSL_read();
15.SSL_shutdown(),SSL_free(),SSL_CTX_free();
服務器端代碼:
#include <stdio.h>
#include <openssl/x509.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <curses.h>
#define MAXSIZE 1024
#define PORT 6666
int main()
{
int err;
char recvbuf[MAXSIZE];
int sockfd,acceptfd;
int bindnes;
struct sockaddr_in server_addr,client_addr;
SSL_CTX *ctx;
SSL *ssl;
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
ctx = SSL_CTX_new(SSLv23_server_method());
if(ctx == NULL)
{
printf("error:%s\n",strerror(errno));
exit(1);
}
SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL);
SSL_CTX_load_verify_locations(ctx,"./openssl/ca.crt",NULL);
if(0 == SSL_CTX_use_certificate_file(ctx,"./openssl/server.crt",SSL_FILETYPE_PEM))
{
printf("error:%s\n",strerror(errno));
exit(1);
}
if(0 == SSL_CTX_use_PrivateKey_file(ctx,"./openssl/server.key",SSL_FILETYPE_PEM))
{
printf("error:%s\n",strerror(errno));
exit(1);
}
if(!SSL_CTX_check_private_key(ctx))
{
printf("error:%s\n",strerror(errno));
exit(1);
}
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd <= 0)
{
printf("socket error:%s\n",strerror(errno));
exit(1);
}
memset(&server_addr,0,sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(PORT);
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
bindnes = bind(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr));
if(bindnes == -1 )
{
printf("bind error:%s\n",strerror(errno));
exit(1);
}
listen(sockfd,10);
socklen_t len = sizeof(client_addr);
acceptfd=accept(sockfd,(struct sockaddr*)&client_addr,&len);
ssl = SSL_new(ctx);
if(ssl == NULL)
{
printf("error:%s:ssl is null",strerror(errno));
exit(1);
}
if(0 == SSL_set_fd(ssl,acceptfd))
{
printf("socket add to SSL error:%s\n",strerror(errno));
exit(1);
}
int k = SSL_accept(ssl);
if(k <= 0)
{
printf("connect fail:%s\n",strerror(errno));
exit(1);
}
X509 *client_crt;
client_crt = SSL_get_peer_certificate(ssl);
printf("find a client try to connect !\n");
while(1)
{
err = SSL_read(ssl,recvbuf,sizeof(recvbuf));
printf("data of buf :%d\n",err);
if(err == 0)
{
printf("client had disconnected\n");
exit(1);
}
recvbuf[err] = '\0';
printf("recvbuf:%s\n",recvbuf);
}
SSL_shutdown(ssl);
SSL_free(ssl);
SSL_CTX_free(ctx);
close(acceptfd);
return 0;
}
客戶端代碼:
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <errno.h>
#include <curses.h>
#include <openssl/rand.h>
#define MAXSIZE 1024
#define PORT 6666
int main()
{
SSL *ssl;
int sockfd;
char sendbuf[MAXSIZE];
SSL_CTX *ctx;
struct sockaddr_in addr;
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
ctx = SSL_CTX_new(SSLv23_client_method());
if(ctx == NULL)
{
printf("error:%s\n",strerror(errno));
exit(1);
}
SSL_CTX_load_verify_locations(ctx,"./openssl/ca.crt",NULL);
if(0 == SSL_CTX_use_certificate_file(ctx,"./openssl/client.crt",SSL_FILETYPE_PEM))
{
printf("error:%s\n",strerror(errno));
exit(1);
}
if(0 == SSL_CTX_use_PrivateKey_file(ctx,"./openssl/client.key",SSL_FILETYPE_PEM))
{
printf("error:%s\n",strerror(errno));
exit(1);
}
if(!SSL_CTX_check_private_key(ctx))
{
printf("error:%s\n",strerror(errno));
exit(1);
}
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd <= 0)
{
printf("socket error:%s\n",strerror(errno));
exit(1);
}
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_port=htons(PORT);
addr.sin_addr.s_addr=htonl(INADDR_ANY);
if(connect(sockfd,(struct sockaddr*)&addr,sizeof(addr)) < 0)
{
printf("connect error:%s\n",strerror(errno));
exit(1);
}
ssl = SSL_new(ctx);
if(NULL == ssl)
{
printf("error:%s\n",strerror(errno));
exit(1);
}
if(SSL_set_fd(ssl,sockfd) <= 0)
{
printf("add ssl error:%s\n",strerror(errno));
exit(1);
}
int k = SSL_connect(ssl);
if(k == 0)
{
printf("connect error:%s\n",strerror(errno));
exit(1);
}
while(1)
{
printf("input the data to send:\n");
scanf("%s",sendbuf);
SSL_write(ssl,sendbuf,strlen(sendbuf));
printf("send msg:%s success\n",sendbuf);
}
SSL_shutdown(ssl);
SSL_free(ssl);
close(sockfd);
SSL_CTX_free(ctx);
return 0;
}