openssl C/C++ SSL安全套接层SOCKET示例,各个API功能详见OPENSSL官方文档。
客户端:
/* g++ -o client ssl_client.cpp -lssl -lcrypt */
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
// openssl header file
#include <openssl/x509.h>
#include <openssl/ssl.h>
//#include <openssl/srtp.h>
#define CA_CERT "cacert.pem"
#define CLIENT_KEY "clientkey.pem"
#define CLIENT_CERT "clientcert.pem"
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 12345
#define RET_IF_EQ(key,val,ret,msg){\
if(key == val){\
fprintf(stderr,"%s failed.\n",msg);\
return ret;\
}else{\
fprintf(stderr,"%s success.\n",msg);\
}\
}
#define RET_IF_LT(key,val,ret,msg){\
if(key < val){\
fprintf(stderr,"%s failed.\n",msg);\
return ret;\
}else{\
fprintf(stderr,"%s success.\n",msg);\
}\
}
int ssl_init(SSL_CTX **ctx,char *pass){
int ret = 0;
OpenSSL_add_ssl_algorithms();
const SSL_METHOD *meth = SSLv23_client_method();
*ctx = SSL_CTX_new(meth);
RET_IF_EQ(*ctx,NULL,-1,"SSL_CTX_new()");
SSL_CTX_set_verify(*ctx,SSL_VERIFY_PEER,NULL);// set verify
SSL_CTX_load_verify_locations(*ctx,CA_CERT,NULL); //load ca cert
ret = SSL_CTX_use_certificate_file(*ctx,CLIENT_CERT,SSL_FILETYPE_PEM);
RET_IF_LT(ret,1,-1,"SSL_CTX_use_certificate_file()");
(*ctx)->default_passwd_callback_userdata = pass;
ret = SSL_CTX_use_PrivateKey_file(*ctx,CLIENT_KEY,SSL_FILETYPE_PEM);
RET_IF_LT(ret,1,-1,"SSL_CTX_use_PrivateKey_file()");
ret = SSL_CTX_check_private_key(*ctx);
RET_IF_EQ(ret,0,-1,"SSL_CTX_check_private_key()");
return 0;
}
int ssl_destroy(SSL_CTX **ctx){
int ret = 0;
SSL_CTX_free(*ctx);
*ctx = NULL;
return ret;
}
int ssl_connect(char *ip,int port,int *fd,SSL **ssl,SSL_CTX *ctx){
int ret = 0;
*fd = socket(AF_INET,SOCK_STREAM,0);
RET_IF_LT(*fd,0,-1,"init_socket()");
struct sockaddr_in sa;
memset(&sa,0,sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr(ip);
sa.sin_port = htons(port);
ret = connect(*fd,(struct sockaddr*)&sa,sizeof(sa));
RET_IF_LT(ret,0,-1,"connect()");
*ssl = SSL_new(ctx);
RET_IF_EQ(*ssl,NULL,-1,"SSL_new");
SSL_set_fd(*ssl,*fd);
ret = SSL_connect(*ssl);
RET_IF_LT(ret,0,-1,"SSL_connect()");
X509 *server_cert = SSL_get_peer_certificate(*ssl);
RET_IF_EQ(server_cert,NULL,-1,"SSL_get_peer_certificate()");
char *str = X509_NAME_oneline(X509_get_subject_name(server_cert),0,0);
fprintf(stderr,"subject:[%s]\n",str);
free(str);
str = X509_NAME_oneline(X509_get_issuer_name(server_cert),0,0);
fprintf(stderr,"issuer:[%s]\n",str);
free(str);
X509_free(server_cert);
return 0;
}
int ssl_disconnect(SSL *ssl,int fd){
SSL_shutdown(ssl);
close(fd);
SSL_free(ssl);
return 0;
}
int main(){
int ret = 0;
SSL_CTX *ctx = NULL;
SSL_METHOD *meth = NULL;
SSL *ssl = NULL;
int fd = 0;
char ip[] = "127.0.0.1";
int port = 12345;
char pass[] = "abc123";
ssl_init(&ctx,pass);
ssl_connect(ip,port,&fd,&ssl,ctx);
int i = 0;
char buf[1025];
for(i=0;i<10;i++){
memset(buf,0,1025);
snprintf(buf,1024,"ssl test send message index:[%d]",i);
ret = SSL_write(ssl,buf,strlen(buf));
fprintf(stderr,"send ret:[%d] msg:[%s]\n",ret,buf);
memset(buf,0,1025);
ret = SSL_read(ssl,buf,1024);
if(ret < 1){
break;
}
fprintf(stderr,"recv ret:[%d] msg:[%s]\n",ret,buf);
}
ssl_disconnect(ssl,fd);
ssl_destroy(&ctx);
return ret;
}
服务端:
/* g++ -o server ssl_server.cpp -lssl -lcrypt */
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
// openssl header file
#include <openssl/x509.h>
#include <openssl/ssl.h>
#define CA_CERT "cacert.pem"
#define CLIENT_KEY "serverkey.pem"
#define CLIENT_CERT "servercert.pem"
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 12345
#define RET_IF_EQ(key,val,ret,msg){\
if(key == val){\
fprintf(stderr,"%s failed.\n",msg);\
return ret;\
}else{\
fprintf(stderr,"%s success.\n",msg);\
}\
}
#define RET_IF_LT(key,val,ret,msg){\
if(key < val){\
fprintf(stderr,"%s failed.\n",msg);\
return ret;\
}else{\
fprintf(stderr,"%s success.\n",msg);\
}\
}
int ssl_init(SSL_CTX **ctx,char *pass){
int ret = 0;
OpenSSL_add_ssl_algorithms();
const SSL_METHOD *meth = SSLv23_server_method();
*ctx = SSL_CTX_new(meth);
RET_IF_EQ(*ctx,NULL,-1,"SSL_CTX_new()");
SSL_CTX_set_verify(*ctx,SSL_VERIFY_PEER,NULL);// set verify
SSL_CTX_load_verify_locations(*ctx,CA_CERT,NULL); //load ca cert
ret = SSL_CTX_use_certificate_file(*ctx,CLIENT_CERT,SSL_FILETYPE_PEM);
RET_IF_LT(ret,1,-1,"SSL_CTX_use_certificate_file()");
(*ctx)->default_passwd_callback_userdata = pass;
ret = SSL_CTX_use_PrivateKey_file(*ctx,CLIENT_KEY,SSL_FILETYPE_PEM);
RET_IF_LT(ret,1,-1,"SSL_CTX_use_PrivateKey_file()");
ret = SSL_CTX_check_private_key(*ctx);
RET_IF_EQ(ret,0,-1,"SSL_CTX_check_private_key()");
return 0;
}
int ssl_destroy(SSL_CTX **ctx){
int ret = 0;
SSL_CTX_free(*ctx);
*ctx = NULL;
return ret;
}
int server_init(char *ip,int port,int *fd){
int ret = 0;
*fd = socket(AF_INET,SOCK_STREAM,0);
RET_IF_LT(*fd,0,-1,"init_sock()");
struct sockaddr_in serv_sa;
memset(&serv_sa,0,sizeof(serv_sa));
serv_sa.sin_family = AF_INET;
serv_sa.sin_addr.s_addr = INADDR_ANY;
serv_sa.sin_port = htons(port);
ret = bind(*fd,(struct sockaddr*)&serv_sa,sizeof(serv_sa));
RET_IF_LT(ret,0,-1,"bind()");
ret = listen(*fd,5);
RET_IF_LT(ret,0,-1,"listen()");
return ret;
}
int server_destroy(int fd){
close(fd);
return 0;
}
int ssl_accept(int listen_fd,int *fd,SSL **ssl,SSL_CTX *ctx){
int ret = 0;
struct sockaddr_in sa;
memset(&sa,0,sizeof(sa));
socklen_t cli_len = sizeof(sa);
*fd = accept(listen_fd,(struct sockaddr*)&sa,&cli_len);
RET_IF_LT(*fd,0,-1,"accept()");
//fprintf(stderr,"accept client fd:[%d] ip:[%s] port:[%d]\n",*fd,sa.sin_addr.s_addr,sa.sin_port);
*ssl = SSL_new(ctx);
RET_IF_EQ(*ssl,NULL,-1,"SSL_new");
SSL_set_fd(*ssl,*fd);
ret = SSL_accept(*ssl);
RET_IF_LT(ret,0,-1,"SSL_connect()");
X509 *server_cert = SSL_get_peer_certificate(*ssl);
RET_IF_EQ(server_cert,NULL,-1,"SSL_get_peer_certificate()");
char *str = X509_NAME_oneline(X509_get_subject_name(server_cert),0,0);
fprintf(stderr,"subject:[%s]\n",str);
free(str);
str = X509_NAME_oneline(X509_get_issuer_name(server_cert),0,0);
fprintf(stderr,"issuer:[%s]\n",str);
free(str);
X509_free(server_cert);
return 0;
}
int ssl_disconnect(SSL *ssl,int fd){
SSL_shutdown(ssl);
close(fd);
SSL_free(ssl);
return 0;
}
int main(){
int ret = 0;
SSL_CTX *ctx = NULL;
SSL *ssl = NULL;
int listen_fd=0,fd = 0;
char ip[] = "127.0.0.1";
int port = 12345;
char pass[] = "abc123";
ssl_init(&ctx,pass);
server_init(ip,port,&listen_fd);
int i =0;
while(1){
ssl_accept(listen_fd,&fd,&ssl,ctx);
i=0;
while(1){
char buf[1025];
memset(buf,0,1025);
ret = SSL_read(ssl,buf,1024);
fprintf(stderr,"recv ret:[%d] msg:[%s]\n",ret,buf);
if(ret < 1) break;
memset(buf,0,1025);
snprintf(buf,1024,"server ssl test send message index:[%d]",i);
ret = SSL_write(ssl,buf,strlen(buf));
fprintf(stderr,"send ret:[%d] msg:[%s]\n",ret,buf);
i++;
}
ssl_disconnect(ssl,fd);
}
ssl_destroy(&ctx);
server_destroy(listen_fd);
return ret;
}