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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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;
}