openssl 编程。 证书制作

openssl证书制作及编程

一、openssl证书制作:

1、创建目录./demoCA/ ./demoCA/newcerts/,创建文件 ./demoCA/index.txt ./demoCA/serial。

2、执行echo 01 > ./demoCA/serial

3、制作自己的CA证书

$openssl req -new -x509 -keyout ca.key -out ca.crt

4、生成服务端的私钥(key文件)及csr文件

$openssl genrsa -des3 -out server.key 1024

$openssl req -new -key server.key -out server.csr

5、生成客户端的私钥(key文件)及csr文件

$openssl genrsa -des3 -out client.key 1024

$openssl req -new -key client.key -out client.csr

6、用生成的CA的证书为刚才生成的server.csr,client.csr文件签名

$openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key

$openssl ca -in client.csr -out client.crt -cert ca.crt -keyfile ca.key

7、生成pem格式证书

有时需要用到pem格式的证书,可以用以下方式合并证书文件(crt)和私钥文件(key)来生成

$cat client.crt client.key> client.pem

$cat server.crt server.key > server.pem

二、openssl编程

      openssl的编程有两种风格:原生态的和层层封装的。

2.1原生态openssl编程

      需要使用BSD socket和openssl中的较底层的API。原生态openssl有两个比较重要的结构SSL和SSL_CTX。

      SSL_CTX数据结构是用与建立SSL/TSL连接的结构,可用于指定通讯协议(SSLv23/TSLv1)、证书、密钥等相关信息。

      SSL数据结构是和具体会话相关联的结构。

常用函数:

      SSL_library_init():初始化一个openssl库。

   SSL_CTX_new(const SSL_METHOD *method):创建一个CTX结构。
   SSL_new(SSL_CTX *ctx):创建一个SSL结构。
   SSL_set_fd(SSL *ssl, int fd):把ssl结构和具体会话相关联。
   SSL_accept(SSL *ssl)、SSL_connect(SSL *ssl):用于SSL会话握手。
   SSL_read(SSL *ssl, void *buf, int num)和SSL_write(SSL *ssl, void *buf, int num)用于SSL读写。
   SSL_shutdown(SSL *ssl)用于关闭一个SSL/TSL会话。
   使用这些函数就可以进行最基本的openssl编程了。Openssl编程框架如下。
 
    
   代码示例:HTTPS服务器和客户端
   服务器端:
 
    
  1. #include <sys/types.h>  
  2. #include <sys/socket.h>  
  3. #include <sys/un.h>  
  4. #include <unistd.h>  
  5. #include <stdio.h>  
  6. #include <arpa/inet.h>  
  7.   
  8. #include <openssl/bio.h>  
  9. #include <openssl/ssl.h>  
  10. #include <openssl/err.h>  
  11.   
  12. #define SERVER_PEM "../digitCert/server.pem"  
  13. #define SERVER_KRY "../digitCert/server.key"  
  14.   
  15. int password_callback(char *buf, int size, int rwflag, void *userdata)  
  16. {  
  17.     /* For the purposes of this demonstration, the password is "ibmdw" */  
  18.     printf("*** Callback function called/n");  
  19.     strcpy(buf,"123456");  
  20.     return strlen(buf);  
  21. }  
  22.   
  23. int main()  
  24. {  
  25.     int serv_sock,cli_sock;  
  26.     socklen_t client_len;  
  27.     struct sockaddr_in server_address;  
  28.     struct sockaddr_in client_address;  
  29.     SSL_CTX * ctx;  
  30.     SSL *ssl;  
  31.   
  32.     int (*callback)(char *, intintvoid *) = &password_callback;  
  33.   
  34.     printf("Serving it up in a secure manner/n/n");  
  35.     SSL_library_init();  
  36.     SSL_load_error_strings();  
  37.     ERR_load_BIO_strings();  
  38.     ERR_load_SSL_strings();  
  39.     OpenSSL_add_all_algorithms();  
  40.   
  41.     printf("Attempting to create SSL context... ");  
  42.     ctx = SSL_CTX_new(SSLv23_server_method());  
  43.     if(ctx == NULL)  
  44.     {  
  45.         printf("Failed. Aborting./n");  
  46.         return 0;  
  47.     }  
  48.   
  49.     printf("/nLoading certificates.../n");  
  50.     SSL_CTX_set_default_passwd_cb(ctx, callback);  
  51.     if(!SSL_CTX_use_certificate_file(ctx, SERVER_PEM, SSL_FILETYPE_PEM))  
  52.     {  
  53.         ERR_print_errors_fp(stdout);  
  54.         SSL_CTX_free(ctx);  
  55.         return 0;  
  56.     }  
  57.     else printf("load server.csr successful!/n");  
  58.     if((SSL_CTX_use_PrivateKey_file(ctx, SERVER_KRY, SSL_FILETYPE_PEM))<=0)  
  59.     {  
  60.         printf("use private key failed!/n/n");  
  61.         ERR_print_errors_fp(stdout);  
  62.         SSL_CTX_free(ctx);  
  63.         return 0;  
  64.     }  
  65.   
  66.     serv_sock = socket(AF_INET,SOCK_STREAM,0);  
  67.     if(-1 == serv_sock){  
  68.         perror("socket");  
  69.     }  
  70.     server_address.sin_family = AF_INET;  
  71.     server_address.sin_port = htons(443);  
  72.     server_address.sin_addr.s_addr = htonl(INADDR_ANY);  
  73.   
  74.     int ret = bind(serv_sock,(struct sockaddr*)&server_address,sizeof(struct sockaddr));  
  75.     if(-1 == ret){  
  76.         perror("bind");  
  77.     }  
  78.     listen(serv_sock,5);  
  79.     while(1){  
  80.         cli_sock = accept(serv_sock,(struct sockaddr *)&client_address,(socklen_t *)&client_len);  
  81.         ssl = SSL_new(ctx);  
  82.         SSL_set_fd (ssl, cli_sock);  
  83.           
  84.         SSL_accept (ssl);  
  85.   
  86.         //读取  
  87.          char line[4096];  
  88.         SSL_read(ssl, line, sizeof (line));  
  89.         //正常处理HTTP协议  
  90.          //写入,返回报文。  
  91.          SSL_write(ssl,"HTTP/1.0 200 OK/r/n/r/n",19);  
  92.         SSL_write(ssl,"<html><header></header><body><p1>Hello World<p1></body></html>",62);  
  93.         close(cli_sock);  
  94.         SSL_shutdown(ssl);  
  95.         SSL_free(ssl);        
  96.     }  
  97.     SSL_CTX_free (ctx);  
  98. }  
   客户端:
 
    
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4. #include <sys/types.h>  
  5. #include <sys/socket.h>  
  6. #include <errno.h>  
  7. #include <unistd.h>  
  8. #include <netinet/in.h>  
  9. #include <limits.h>  
  10. #include <netdb.h>  
  11. #include <arpa/inet.h>  
  12. #include <ctype.h>  
  13. #include <openssl/crypto.h>  
  14. #include <openssl/ssl.h>  
  15. #include <openssl/err.h>  
  16. #include <openssl/rand.h>  
  17.   
  18. #define DEBUG 1  
  19.   
  20. /******************************************** 
  21. 功能:搜索字符串右边起的第一个匹配字符 
  22. ********************************************/  
  23. char *Rstrchr(char *s, char x)  
  24. {  
  25.     int i = strlen(s);  
  26.     if (!(*s))  
  27.         return 0;  
  28.     while (s[i - 1])  
  29.         if (strchr(s + (i - 1), x))  
  30.             return (s + (i - 1));  
  31.         else  
  32.             i--;  
  33.     return 0;  
  34. }  
  35.   
  36. /************************************************************** 
  37. 功能:从字符串src中分析出网站地址和端口,并得到用户要下载的文件 
  38. ***************************************************************/  
  39. void GetHost(char *src, char *web, char *file, int *port)  
  40. {  
  41.     char *pA;  
  42.     char *pB;  
  43.     memset(web, 0, sizeof(web));  
  44.     memset(file, 0, sizeof(file));  
  45.     *port = 0;  
  46.     if (!(*src))  
  47.         return;  
  48.     pA = src;  
  49.     if (!strncmp(pA, "http://", strlen("http://")))  
  50.         pA = src + strlen("http://");  
  51.     else if (!strncmp(pA, "https://", strlen("https://")))  
  52.         pA = src + strlen("https://");  
  53.     pB = strchr(pA, '/');  
  54.     if (pB) {  
  55.         memcpy(web, pA, strlen(pA) - strlen(pB));  
  56.         if (pB + 1) {  
  57.             memcpy(file, pB + 1, strlen(pB) - 1);  
  58.             file[strlen(pB) - 1] = 0;  
  59.         }  
  60.     } else  
  61.         memcpy(web, pA, strlen(pA));  
  62.     if (pB)  
  63.         web[strlen(pA) - strlen(pB)] = 0;  
  64.     else  
  65.         web[strlen(pA)] = 0;  
  66.     pA = strchr(web, ':');  
  67.     if (pA)  
  68.         *port = atoi(pA + 1);  
  69.     else  
  70.         *port = 443;  
  71. }  
  72.   
  73. /************关于本文档******************************************** 
  74. *filename: https-client.c 
  75. *purpose: 演示HTTPS客户端编程方法 
  76. *wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com) 
  77. Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言 
  78. *date time:2007-01-30 20:06 
  79. *Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途 
  80. * 但请遵循GPL 
  81. *Thanks to:Google 
  82. *Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力 
  83. * 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献! 
  84. *********************************************************************/  
  85.   
  86. int main(int argc, char *argv[])  
  87. {  
  88.     int sockfd, ret;  
  89.     char buffer[1024];  
  90.     struct sockaddr_in server_addr;  
  91.     struct hostent *host;  
  92.     int portnumber, nbytes;  
  93.     char host_addr[256];  
  94.     char host_file[1024];  
  95.     char local_file[256];  
  96.     FILE *fp;  
  97.     char request[1024];  
  98.     int send, totalsend;  
  99.     int i;  
  100.     char *pt;  
  101.     SSL *ssl;  
  102.     SSL_CTX *ctx;  
  103.   
  104.     if (argc != 2) {  
  105.         if (DEBUG)  
  106.             fprintf(stderr, "Usage:%s webpage-address/a/n", argv[0]);  
  107.         exit(1);  
  108.     }  
  109.     if (DEBUG)  
  110.         printf("parameter.1 is: %s/n", argv[1]);  
  111.   
  112.     GetHost(argv[1], host_addr, host_file, &portnumber);        /*分析网址、端口、文件名等 */  
  113.     if (DEBUG)  
  114.         printf("webhost:%s/n", host_addr);  
  115.     if (DEBUG)  
  116.         printf("hostfile:%s/n", host_file);  
  117.     if (DEBUG)  
  118.         printf("portnumber:%d/n/n", portnumber);  
  119.   
  120.     if ((host = gethostbyname(host_addr)) == NULL) {        /*取得主机IP地址 */  
  121.         if (DEBUG)  
  122.             fprintf(stderr, "Gethostname error, %s/n", strerror(errno));  
  123.         exit(1);  
  124.     }  
  125.   
  126.     /* 客户程序开始建立 sockfd描述符 */  
  127.     if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {        /*建立SOCKET连接 */  
  128.         if (DEBUG)  
  129.             fprintf(stderr, "Socket Error:%s/a/n", strerror(errno));  
  130.         exit(1);  
  131.     }  
  132.   
  133.     /* 客户程序填充服务端的资料 */  
  134.     bzero(&server_addr, sizeof(server_addr));  
  135.     server_addr.sin_family = AF_INET;  
  136.     server_addr.sin_port = htons(portnumber);  
  137.     server_addr.sin_addr = *((struct in_addr *) host->h_addr);  
  138.   
  139.     /* 客户程序发起连接请求 */  
  140.     if (connect(sockfd, (struct sockaddr *) (&server_addr), sizeof(struct sockaddr)) == -1) {        /*连接网站 */  
  141.         if (DEBUG)  
  142.             fprintf(stderr, "Connect Error:%s/a/n", strerror(errno));  
  143.         exit(1);  
  144.     }  
  145.   
  146.     /* SSL初始化 */  
  147.     SSL_library_init();  
  148.     SSL_load_error_strings();  
  149.     ctx = SSL_CTX_new(SSLv23_client_method());  
  150.     if (ctx == NULL) {  
  151.         ERR_print_errors_fp(stderr);  
  152.         exit(1);  
  153.     }  
  154.   
  155.     ssl = SSL_new(ctx);  
  156.     if (ssl == NULL) {  
  157.         ERR_print_errors_fp(stderr);  
  158.         exit(1);  
  159.     }  
  160.   
  161.     /* 把socket和SSL关联 */  
  162.     ret = SSL_set_fd(ssl, sockfd);  
  163.     if (ret == 0) {  
  164.         ERR_print_errors_fp(stderr);  
  165.         exit(1);  
  166.     }  
  167.   
  168.     RAND_poll();  
  169.     while (RAND_status() == 0) {  
  170.         unsigned short rand_ret = rand() % 65536;  
  171.         RAND_seed(&rand_ret, sizeof(rand_ret));  
  172.     }  
  173.   
  174.     ret = SSL_connect(ssl);  
  175.     if (ret != 1) {  
  176.         ERR_print_errors_fp(stderr);  
  177.         exit(1);  
  178.     }  
  179.   
  180.     sprintf(request, "GET /%s HTTP/1.1/r/nAccept: */*/r/nAccept-Language: zh-cn/r/n/ 
  181. User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)/r/n/ 
  182. Host: %s:%d/r/nConnection: Close/r/n/r/n", host_file, host_addr, 
  183.             portnumber); 
  184.     if (DEBUG) 
  185.         printf("%s", request);        /*准备request,将要发送给主机 */  
  186.   
  187.     /*取得真实的文件名 */  
  188.     if (host_file && *host_file)  
  189.         pt = Rstrchr(host_file, '/');  
  190.     else  
  191.         pt = 0;  
  192.   
  193.     memset(local_file, 0, sizeof(local_file));  
  194.     if (pt && *pt) {  
  195.         if ((pt + 1) && *(pt + 1))  
  196.             strcpy(local_file, pt + 1);  
  197.         else  
  198.             memcpy(local_file, host_file, strlen(host_file) - 1);  
  199.     } else if (host_file && *host_file)  
  200.         strcpy(local_file, host_file);  
  201.     else  
  202.         strcpy(local_file, "index.html");  
  203.     if (DEBUG)  
  204.         printf("local filename to write:%s/n/n", local_file);  
  205.   
  206.     /*发送https请求request */  
  207.     send = 0;  
  208.     totalsend = 0;  
  209.     nbytes = strlen(request);  
  210.     while (totalsend < nbytes) {  
  211.         send = SSL_write(ssl, request + totalsend, nbytes - totalsend);  
  212.         if (send == -1) {  
  213.             if (DEBUG)  
  214.                 ERR_print_errors_fp(stderr);  
  215.             exit(0);  
  216.         }  
  217.         totalsend += send;  
  218.         if (DEBUG)  
  219.             printf("%d bytes send OK!/n", totalsend);  
  220.     }  
  221.   
  222.     fp = fopen("index.html""a");  
  223.     if (!fp) {  
  224.         if (DEBUG)  
  225.             printf("create file error! %s/n", strerror(errno));  
  226.         return 0;  
  227.     }  
  228.     if (DEBUG)  
  229.         printf("/nThe following is the response header:/n");  
  230.     i = 0;  
  231.     /* 连接成功了,接收https响应,response */  
  232.     while ((nbytes = SSL_read(ssl, buffer, 1)) == 1) {  
  233.         if (i < 4) {  
  234.             if (buffer[0] == '/r' || buffer[0] == '/n')  
  235.                 i++;  
  236.             else  
  237.                 i = 0;  
  238.             if (DEBUG)  
  239.                 printf("%c", buffer[0]);        /*把https头信息打印在屏幕上 */  
  240.         } else {  
  241.             fwrite(buffer, 1, 1, fp);        /*将https主体信息写入文件 */  
  242.             i++;  
  243.             if (i % 1024 == 0)  
  244.                 fflush(fp);        /*每1K时存盘一次 */  
  245.         }  
  246.     }  
  247.     fclose(fp);  
  248.     /* 结束通讯 */  
  249.     ret = SSL_shutdown(ssl);  
  250.     if (ret != 1) {  
  251.         ERR_print_errors_fp(stderr);  
  252.         exit(1);  
  253.     }  
  254.     close(sockfd);  
  255.     SSL_free(ssl);  
  256.     SSL_CTX_free(ctx);  
  257.     ERR_free_strings();  
  258.     exit(0);  
  259. }  
2.2层层封装的openssl编程。

     这里BSD socket的基本操作,对上层是不可见的。而且openssl自己有对自己的底层操作进行了封装。

     除此之外还需要了解BIO的概念。

     BIO是openssl 对于io 类型的抽象封装,包括:内存、文件、日志、标准输入输出、socket、加/解密、摘要和ssl 通道等。

     BIO分为两种:source/sink类型的BIO是数据源或输入数据源(我不知道sink该怎么翻译),例如,sokect BIO和文件BIO。而filter BIO就是把数据从一个BIO转换到另外一个BIO或应用接口,在转换过程中,这些数据可以不修改(如信息摘要BIO),也可以进行转换。

     BIO链,可以预先设定好多个BIO之间的链接关系,当数据从source类型的BIO进来之后,数据自动再BIO链之间传递。这应该是BIO有吸引力的地方。比如三个BIO,mbio(内存类型),sbio(ssl类型),abio(accept类型),连成BIO链:mbio->sbio->abio。

     那么对mbio的读操作实际上就包含了从accept接收数据、对加密数据ssl解密,最终把数据读到内存中的操作;对mbio的写操作实际上包含了对数据进行ssl加密,并把加密数据从socket发出去的操作。

BIO常用函数:

     BIO * BIO_new(BIO_METHOD *type):生成BIO

     BIO_set(BIO *a,BIO_METHOD *type):设置BIO

     BIO_free(BIO *a):删除BIO

     BIO_free_all(BIO *a):删除BIO链

     BIO_read(BIO *b, void *buf, int len)

     BIO_gets(BIO *b,char *buf, int size)

     BIO_write(BIO *b, const void *buf, int len)

     BIO_puts(BIO *b,const char *buf)

     BIO * BIO_push(BIO *b,BIO *append):该函数把参数中名为append的BIO附加到名为b的BIO上,并返回b。

     BIO * BIO_pop(BIO *b):为b的BIO从一个BIO链中移除并返回下一个BIO。

     代码示例(echo):
     服务器端:
 
    
  1. #include <stdio.h>  
  2. #include <string.h>  
  3.   
  4. #include <openssl/bio.h>  
  5. #include <openssl/ssl.h>  
  6. #include <openssl/err.h>  
  7. #include <unistd.h>  
  8.   
  9. #define SERVER_PEM "../digitCert/server.pem"  
  10. #define SERVER_KRY "../digitCert/server.key"  
  11.   
  12. int password_callback(char *buf, int size, int rwflag, void *userdata)  
  13. {  
  14.     /* For the purposes of this demonstration, the password is "ibmdw" */  
  15.   
  16.     printf("*** Callback function called/n");  
  17.     strcpy(buf,"123456");  
  18.     return strlen(buf);  
  19. }  
  20.   
  21. int main()  
  22. {  
  23.     SSL_CTX *ctx;  
  24.     SSL *ssl;  
  25.     BIO *sslbio, *acptbio, *out;  
  26.     pid_t pid;  
  27.     int len;  
  28.     char buf[1024];  
  29.   
  30.     int (*callback)(char *, intintvoid *) = &password_callback;  
  31.   
  32.     printf("Secure Programming with the OpenSSL API, Part 4:/n");  
  33.     printf("Serving it up in a secure manner/n/n");  
  34.   
  35.     SSL_library_init();  
  36.     SSL_load_error_strings();  
  37.     ERR_load_BIO_strings();  
  38.     ERR_load_SSL_strings();  
  39.     OpenSSL_add_all_algorithms();  
  40.   
  41.     printf("Attempting to create SSL context... ");  
  42.     ctx = SSL_CTX_new(SSLv23_server_method());  
  43.     if(ctx == NULL)  
  44.     {  
  45.         printf("Failed. Aborting./n");  
  46.         return 0;  
  47.     }  
  48.   
  49.     printf("/nLoading certificates.../n");  
  50.     SSL_CTX_set_default_passwd_cb(ctx, callback);  
  51.     if(!SSL_CTX_use_certificate_file(ctx, SERVER_PEM, SSL_FILETYPE_PEM))  
  52.     {  
  53.         ERR_print_errors_fp(stdout);  
  54.         SSL_CTX_free(ctx);  
  55.         return 0;  
  56.     }  
  57.     else printf("load server.csr successful!/n");  
  58.     if((SSL_CTX_use_PrivateKey_file(ctx, SERVER_KRY, SSL_FILETYPE_PEM))<=0)  
  59.     {  
  60.         printf("use private key failed!/n/n");  
  61.         ERR_print_errors_fp(stdout);  
  62.         SSL_CTX_free(ctx);  
  63.         return 0;  
  64.     }  
  65.   
  66.     printf("Attempting to create BIO object... ");  
  67.     sslbio = BIO_new_ssl(ctx, 0);//0 indicate using server mode  
  68.     if(sslbio == NULL)  
  69.     {  
  70.         printf("Failed. Aborting./n");  
  71.         ERR_print_errors_fp(stdout);  
  72.         SSL_CTX_free(ctx);  
  73.         return 0;  
  74.     }  
  75.   
  76.     printf("/nAttempting to set up BIO for SSL.../n");  
  77.     BIO_get_ssl(sslbio, &ssl);  
  78.   
  79.     printf("Waiting for incoming connection.../n");  
  80.     /*Begin to listen the port*/  
  81.     if(BIO_do_accept(acptbio) <= 0)  
  82.     {  
  83.         ERR_print_errors_fp(stdout);  
  84.         SSL_CTX_free(ctx);  
  85.         BIO_free_all(sslbio);  
  86.         BIO_free_all(acptbio);  
  87.         return 1;  
  88.     }  
  89.     while(1)  
  90.     {  
  91.         /*Waiting for a new connection to establish*/  
  92.         if(BIO_do_accept(acptbio) <= 0)  
  93.         {  
  94.                 ERR_print_errors_fp(stdout);  
  95.                 SSL_CTX_free(ctx);  
  96.                 BIO_free_all(sslbio);  
  97.                 BIO_free_all(acptbio);  
  98.                 return 1;  
  99.         }  
  100.         out = BIO_pop(acptbio);  
  101.   
  102.          if((pid=fork()))//parent process  
  103.     {  
  104.             BIO_free(out);  
  105.     }  
  106.     else  
  107.     {  
  108.             if(BIO_do_handshake(out) <= 0)  
  109.             {  
  110.                 printf("Handshake failed./n");  
  111.                 ERR_print_errors_fp(stdout);  
  112.                 SSL_CTX_free(ctx);  
  113.                 BIO_free_all(sslbio);  
  114.                 BIO_free_all(acptbio);  
  115.                 return 1;  
  116.             }  
  117.             for(;;)  
  118.             {  
  119.                 memset(buf,0,1023);  
  120.                 len = BIO_read(out,buf,1023);  
  121.                                          switch(SSL_get_error(ssl,len))  
  122.                 {  
  123.                     case SSL_ERROR_NONE:  
  124.                         break;  
  125.                     default:  
  126.                         printf("Read Problem!/n");  
  127.                         exit(0);  
  128.                 }  
  129.                 if(!strcmp(buf,"/r/n")||!strcmp(buf,"/n"))  
  130.                     break;  
  131.                 if(buf[0]=='q')   
  132.                        break;  
  133.                 BIO_write(out,buf,len);  
  134.                 printf("%s/n",buf);  
  135.             }     
  136.             BIO_free(out);  
  137.             BIO_ssl_shutdown(sslbio);  
  138.             exit(0);  
  139.     }//end else  
  140.     }  
  141.     BIO_ssl_shutdown(sslbio);  
  142.     BIO_free_all(sslbio);  
  143.     BIO_free_all(acptbio);  
  144.     SSL_CTX_free(ctx);  
  145. }  
    客户端:
  
  1. #include <openssl/ssl.h>  
  2. #include <errno.h>  
  3. #include <openssl/bio.h>  
  4. #include <openssl/err.h>  
  5.   
  6. #include <stdio.h>  
  7. #include <string.h>  
  8.   
  9. int main()  
  10. {  
  11.     BIO *sslbio;  
  12.     SSL * ssl;  
  13.     SSL_CTX * ctx;  
  14.   
  15.     int p;  
  16.   
  17.   
  18.     /* Set up the library */  
  19.     SSL_library_init();//一定要有,初始化ssl库  
  20.     ERR_load_BIO_strings();  
  21.     SSL_load_error_strings();  
  22.     OpenSSL_add_all_algorithms();  
  23.   
  24.     /* Set up the SSL context */  
  25.   
  26.     ctx = SSL_CTX_new(SSLv23_method());  
  27.   
  28.     /* Load the trust store */  
  29.   
  30.     if(!SSL_CTX_load_verify_locations(ctx, "../digitCert/ca.crt",0))//读取CA根证书,用这个证书来验证对方的证书是否可信  
  31.     {  
  32.         fprintf(stderr, "Error loading trust store/n");  
  33.         SSL_CTX_free(ctx);  
  34.         return 0;  
  35.     }  
  36.   
  37.     /* Setup the connection */  
  38.   
  39.     sslbio = BIO_new_ssl_connect(ctx);//建立ssl类型的bio  
  40.   
  41.     /* Set the SSL_MODE_AUTO_RETRY flag */  
  42.   
  43.     BIO_get_ssl(sslbio, & ssl);//从已建立的ssl类型的bio sslbio中得到ssl变量  
  44.     SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);//设置ssl的模式为SSL_MODE_AUTO_RETRY,使用这个选项进行设置,如果服务器突然希望进行一次新的握手,那么OpenSSL 可以在后台处理它。  
  45.       
  46.   
  47.     /* Create and setup the connection */  
  48.   
  49.     BIO_set_conn_hostname(sslbio, "127.0.0.1:4433");  
  50.   
  51.     if(BIO_do_connect(sslbio) <= 0)//发起握手请求  
  52.     {  
  53.         fprintf(stderr, "Error attempting to connect/n");  
  54.         ERR_print_errors_fp(stderr);  
  55.         BIO_free_all(sslbio);  
  56.         SSL_CTX_free(ctx);  
  57.         return 0;  
  58.     }  
  59.     else printf("connent to server successful!/n");  
  60.   
  61.     /* Check the certificate */  
  62.   
  63.     if(SSL_get_verify_result(ssl) != X509_V_OK)//验证对方的证书是否是合法的(时间未过期,等等。。。)  
  64.     {  
  65.         fprintf(stderr, "Certificate verification error: %ld/n", SSL_get_verify_result(ssl));  
  66.         BIO_free_all(sslbio);  
  67.         SSL_CTX_free(ctx);  
  68.         return 0;  
  69.     }  
  70.     else printf("verify server cert successful/n");  
  71.   
  72.     char buf[1024];  
  73.     for(;;)  
  74.     {  
  75.         printf("/ninput:");  
  76.             scanf("%s",&buf[0]);  
  77.         BIO_write(sslbio,buf,strlen(buf));  
  78.         p = BIO_read(sslbio, buf, 1023);  
  79.         if(p <= 0) break;  
  80.         buf[p] = 0;  
  81.         printf("%s/n", buf);  
  82.         memset(buf,0,1024);  
  83.     }  
  84.   
  85.     /* Close the connection and free the context */  
  86.     BIO_ssl_shutdown(sslbio);  
  87.     BIO_free_all(sslbio);  
  88.     SSL_CTX_free(ctx);  
  89.     return 0;  
  90. }  
个人分类:  网络协议 linux 编程
想对作者说点什么?  我来说一句
  • ben_lbj
    ben_lbj 2016-06-30 15:06:59 #4楼
    感谢分享!!关注
  • pingD
    pingd 2015-08-06 16:29:41 #3楼
    受益了
  • swtheking
    swtheking 2013-08-27 16:23:20 #2楼
    能给我一份源码么?亲
  • swtheking
    swtheking 2013-08-27 15:41:11 #1楼
    你的https服务器能和正常的网页交互么
查看 4 条热评
OpenSSL证书制作

2015年12月22日 2KB 下载 

OpenSSL证书制作过程

2011年12月01日 222KB 下载 

个人资料

原创
39
粉丝
241
喜欢
6
评论
173
等级:
访问:
69万+
积分:
5080
排名:
7365

热门文章

最新评论

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值