zoukankan      html  css  js  c++  java
  • openssl使用+Demo

    1. website
    SSL(secure Socket Layer)
    TLS(transport Layer Security) - SSL3.0基础之上提出的安全通信标准,目前版本是1.0
    openssl 主页 -> http://www.openssl.org/
    openssl 中文文档 -> http://www.chinaunix.net/jh/13/478901.html

    2. 如何编译OpenSSL in Windows?
    a) 下载openssl -> openssl-0.9.8i
    b) 下载perl -> http://downloads.activestate.com/ActivePerl/Windows/5.8/ActivePerl-5.8.8.822-MSWin32-x86-280952.zip
    c) 安装perl -> ActivePerl-5.8.8.822-MSWin32-x86-280952/Installer.bat (之前先运行vcvars32.bat,需要运行perf Configure VC-WIN32来设置环境变量)
    d) 使windows支持nmake -> C:Program FilesMicrosoft Visual Studio 10.0VCinvcvars32.bat
    e) 进入openssl路径 -> cd C:devdivopenssl-0.9.8i    (工作路径)
    f) 创建Makefile文件: msdo_ms     (出现%osversion% is not defined的错误忽略即可)
    g) 编译动态库: nmake -f ms tdll.mak
       编译静态库: nmake -f ms t.mak

       测试动态库: nmake -f ms tdll.mak test
       测试静态库: nmake -f ms t.mak test

       安装动态库: nmake -f ms tdll.mak install
       安装静态库: nmake -f ms t.mak install

       清除上次动态库的编译,以便重新编译: nmake -f ms tdll.mak clean
       清除上次静态库的编译,以便重新编译: nmake -f ms t.mak clean
       
    3. 如何使用openssl?
    a) library path -> C:devdivopenssl-0.9.8iout32
    b) include path -> C:devdivopenssl-0.9.8iinclude
    c) 库文件 -> libeay32.lib, ssleay32.lib

    4. 配置文件在哪里?
    C:devdivopenssl-0.9.8iappsopenssl.cnf

    5. 关于key:
    key一般分为public key和private key,在openssl中,private key中包含了public key的信息,所以public key不需要单独创建. 如何创建一个RSA key?
    openssl.exe genrsa -des3 -out privatekey.pem 2048  (需要添加密码保护)
    openssl.exe genrsa -out privatekey.pem 2048

    6. 关于certificates(证书文件), 如何创建一个证书呢?
    一般流程是:
    a. 创建一个private key
    b. 创建一个certificate signing request(证书请求), 这个需要a#中创建的private key.因为证书中需要包含public key,
    创建的priavate key中有这些信息.
    (openssl.exe req -new -key privatekey.pem-out cacert.csr)
    c. 把创建好的证书请求拿到CA(certificate authority)证书认证机构审批.

    7. 如何做一个自签名的证书呢?
    openssl.exe req -new -x509 -key privatekey.pem -out cacert.pem -days 1095
    (Note: privatekey.pem需要自己创建)

    8. Demo: 来自openssl自带的demo,略做修改.
    Server:

      1#include <openssl/rsa.h>       /* SSLeay stuff */
      2#include <openssl/crypto.h>
      3#include <openssl/x509.h>
      4#include <openssl/pem.h>
      5#include <openssl/ssl.h>
      6#include <openssl/err.h>
      7
      8
      9#include <iostream>
     10#include <winsock2.h>
     11
     12#define SERVER_PORT    5003
     13
     14// certificate & key 的存放路径
     15// Note: 必须是全路径, 否则SSL_CTX_use_certificate_file等函数
     16//       无法找到文件在windows平台上.
     17// How to:
     18// #privatekey.pem
     19// openssl.exe genrsa -out privatekey.pem 2048
     20// #cacert.pem
     21// openssl.exe req -new -x509 -key privatekey.pem -out cacert.pem -days 1095 -config openssl.cnf
     22//
     23#define SERVER_CERTIFICATE   "c:\config\cacert.pem"    
     24#define SERVER_KEY           "c:\config\privatekey.pem"
     25
     26#pragma comment( lib, "ws2_32.lib" )
     27#pragma comment( lib, "libeay32.lib" )
     28#pragma comment( lib, "ssleay32.lib" )
     29
     30int main( int argc, char* argv[] ) {
     31  int ret;
     32
     33  ////////////
     34  // 初始化 //
     35  ////////////
     36  SSL_CTX* ctx;
     37  SSL_METHOD *meth;
     38
     39  SSL_load_error_strings();
     40  SSLeay_add_ssl_algorithms();
     41  meth = SSLv23_server_method(); 
     42
     43  ctx = SSL_CTX_new (meth);
     44  if (!ctx) {
     45    ERR_print_errors_fp(stderr);
     46    std::cout<<"SSL_CTX_new error."<<std::endl;
     47    return -1;
     48  }
     49  
     50  if (SSL_CTX_use_certificate_file(ctx, SERVER_CERTIFICATE, SSL_FILETYPE_PEM) <= 0) {
     51    ERR_print_errors_fp(stderr);
     52    std::cout<<"SSL_CTX_use_certificate_file error."<<std::endl;
     53    return -1;
     54  }
     55  if (SSL_CTX_use_PrivateKey_file(ctx, SERVER_KEY, SSL_FILETYPE_PEM) <= 0) {
     56    ERR_print_errors_fp(stderr);
     57    std::cout<<"SSL_CTX_use_PrivateKey_file error."<<std::endl;
     58    return -1;
     59  }
     60
     61  if (!SSL_CTX_check_private_key(ctx)) {
     62    ERR_print_errors_fp(stderr);
     63    std::cout<<"SSL_CTX_check_private_key error."<<std::endl;
     64    return -1;
     65  }
     66
     67  ///////////////////////
     68  // 建立原始的TCP连接 //
     69  ///////////////////////
     70  WSADATA wsaData;
     71  SOCKET listen_socket;
     72  SOCKET accept_socket;
     73  struct sockaddr_in addr_server;
     74  struct sockaddr_in addr_client;
     75  int addr_client_len;
     76
     77  ret = WSAStartup( MAKEWORD(2, 2), &wsaData );
     78  if ( ret != 0 ) {
     79    std::cout<<"WSAStartup error."<<std::endl;
     80    return -1;
     81  }
     82
     83  listen_socket = socket (AF_INET, SOCK_STREAM, 0);  
     84  if( listen_socket == INVALID_SOCKET  ) {
     85    std::cout<<"socket error."<<std::endl;
     86    return -1;
     87  }
     88  
     89  memset (&addr_server, 0, sizeof(addr_server));
     90  addr_server.sin_family           = AF_INET;
     91  addr_server.sin_addr.S_un.S_addr = INADDR_ANY;
     92  addr_server.sin_port             = htons (SERVER_PORT);        
     93  
     94  ret = bind(listen_socket, (struct sockaddr*)&addr_server, sizeof(addr_server) ); 
     95  if( ret == SOCKET_ERROR )  {
     96     std::cout<<"bind error."<<std::endl;
     97     return -1;
     98  }
     99         
    100  ret = listen (listen_socket, 5); 
    101  if( ret == SOCKET_ERROR ) {
    102    std::cout<<"listen error."<<std::endl;
    103    return -1;
    104  }
    105  
    106  addr_client_len = sizeof(addr_client);
    107  accept_socket = accept (listen_socket, (struct sockaddr*) &addr_client, &addr_client_len);
    108  if( accept_socket == INVALID_SOCKET  ) {
    109    std::cout<<"accept error."<<std::endl;
    110    return -1;
    111  }
    112  closesocket(listen_socket);
    113  std::cout<<" Connection from "<<addr_client.sin_addr.S_un.S_addr<<":"<<addr_client.sin_port<<std::endl;
    114
    115  /////////////////////////////////////
    116  // TCP连接已经建立,执行Server SSL //
    117  /////////////////////////////////////
    118  SSL*     ssl;
    119  X509*    client_certificate;
    120  char*    str;
    121
    122  ssl = SSL_new (ctx);                           
    123  if( ssl == NULL ) {
    124    std::cout<<"SSL_new error."<<std::endl;
    125    return -1;
    126  } 
    127  SSL_set_fd (ssl, accept_socket);
    128  ret = SSL_accept (ssl);                     
    129  if( ret == -1 ) {
    130    std::cout<<"SSL_accept error."<<std::endl;
    131    return -1;
    132  }
    133  
    134  // 获取cipher
    135  std::cout<<"SSL connection using: "<<SSL_get_cipher(ssl)<<std::endl;
    136  
    137  // 获取客户端的证书
    138  client_certificate = SSL_get_peer_certificate (ssl);
    139  if (client_certificate != NULL) {
    140    std::cout<<"Client certificate:"<<std::endl;
    141    
    142    str = X509_NAME_oneline (X509_get_subject_name (client_certificate), 0, 0);
    143    if( str == NULL ) {
    144      std::cout<<"X509_NAME_oneline error."<<std::endl;
    145    } else {
    146      std::cout<<"subject: "<<str<<std::endl;
    147      OPENSSL_free (str);
    148    }
    149    
    150    str = X509_NAME_oneline (X509_get_issuer_name  (client_certificate), 0, 0);
    151    if( str == NULL ) {
    152      std::cout<<"X509_NAME_oneline error."<<std::endl;
    153    } else {
    154      std::cout<<"issuer: "<<str<<std::endl;
    155      OPENSSL_free (str);
    156    }
    157
    158    X509_free (client_certificate);
    159  } else {
    160    std::cout<<"Client does not have certificate. "<<std::endl;
    161  }
    162
    163  ////////////////
    164  //  数据交换  //
    165  ////////////////
    166  char     buf [4096];
    167
    168  ret = SSL_read (ssl, buf, sizeof(buf) - 1);    
    169  if( ret == -1 ) {
    170    std::cout<<"SSL_read error."<<std::endl;
    171    return -1;
    172  }
    173  buf[ret] = '';
    174  std::cout<<buf<<std::endl;
    175  
    176  ret = SSL_write (ssl, "I hear you.", strlen("I hear you.")); 
    177  if( ret == -1 ) {
    178    std::cout<<"SSL_write error."<<std::endl;
    179    return -1;
    180  }
    181
    182  /////////////
    183  // Cleanup //
    184  /////////////
    185  closesocket(accept_socket);
    186  SSL_free (ssl);
    187  SSL_CTX_free (ctx);
    188  WSACleanup();
    189  return 0;
    190}

    Client:

      1#include <openssl/rsa.h>       /* SSLeay stuff */
      2#include <openssl/crypto.h>
      3#include <openssl/x509.h>
      4#include <openssl/pem.h>
      5#include <openssl/ssl.h>
      6#include <openssl/err.h>
      7
      8
      9#include <iostream>
     10#include <winsock2.h>
     11
     12#define SERVER_IP      "127.0.0.1"
     13#define SERVER_PORT    5003
     14
     15#pragma comment( lib, "ws2_32.lib" )
     16#pragma comment( lib, "libeay32.lib" )
     17#pragma comment( lib, "ssleay32.lib" )
     18
     19
     20int main( int argc, char* argv[] ) {
     21  int ret;
     22  ////////////
     23  // 初始化 //
     24  ////////////
     25  SSL_CTX* ctx;
     26  SSL_METHOD *meth;
     27
     28  SSL_load_error_strings();
     29  SSLeay_add_ssl_algorithms();
     30  meth = SSLv23_client_method();
     31
     32  ctx = SSL_CTX_new (meth);
     33  if (!ctx) {
     34    ERR_print_errors_fp(stderr);
     35    std::cout<<"SSL_CTX_new error."<<std::endl;
     36    return -1;
     37  }
     38
     39  ///////////////////////
     40  // 建立原始的TCP连接 //
     41  ///////////////////////
     42  WSADATA wsaData;
     43  SOCKET client_socket;
     44  struct sockaddr_in addr_server;
     45
     46  ret = WSAStartup( MAKEWORD(2, 2), &wsaData );
     47  if ( ret != 0 ) {
     48    std::cout<<"WSAStartup error."<<std::endl;
     49    return -1;
     50  }
     51  client_socket = socket (AF_INET, SOCK_STREAM, 0);  
     52  if( client_socket == INVALID_SOCKET  ) {
     53    std::cout<<"socket error."<<std::endl;
     54    return -1;
     55  }
     56  
     57  memset (&addr_server, 0, sizeof(addr_server));
     58  addr_server.sin_family           = AF_INET;
     59  addr_server.sin_addr.S_un.S_addr = inet_addr(SERVER_IP);
     60  addr_server.sin_port             = htons (SERVER_PORT);
     61
     62  ret = connect(client_socket, (struct sockaddr*) &addr_server, sizeof(addr_server)); 
     63  if( client_socket == SOCKET_ERROR  ) {
     64    std::cout<<"connect error."<<std::endl;
     65    return -1;
     66  }
     67
     68  /////////////////////////////////////
     69  // TCP连接已经建立,执行Client SSL //
     70  /////////////////////////////////////
     71  SSL*     ssl;
     72  X509*    server_certificate;
     73  char*    str;
     74
     75  ssl = SSL_new (ctx);                         
     76  if( ssl == NULL ) {
     77    std::cout<<"SSL_new error."<<std::endl;
     78    return -1;
     79  } 
     80  SSL_set_fd (ssl, client_socket);
     81  ret = SSL_connect (ssl);                     
     82  if( ret == -1 ) {
     83    std::cout<<"SSL_accept error."<<std::endl;
     84    return -1;
     85  }
     86    
     87  // 接下来的获取密码和获取服务器端证书的两部是可选的,不会影响数据交换
     88  
     89  // 获取cipher
     90  std::cout<<"SSL connection using: "<<SSL_get_cipher(ssl)<<std::endl;
     91  
     92  // 获取服务器端的证书
     93  server_certificate = SSL_get_peer_certificate (ssl);       
     94  if( server_certificate != NULL ) {
     95    std::cout<<"Server certificate:"<<std::endl;
     96
     97    str = X509_NAME_oneline (X509_get_subject_name (server_certificate),0,0);
     98    if( str == NULL ) {
     99      std::cout<<"X509_NAME_oneline error."<<std::endl;
    100    } else {
    101      std::cout<<"subject: "<<str<<std::endl;
    102      OPENSSL_free (str);
    103    }
    104
    105    str = X509_NAME_oneline (X509_get_issuer_name  (server_certificate),0,0);
    106    if( str == NULL ) {
    107      std::cout<<"X509_NAME_oneline error."<<std::endl;
    108    } else {
    109      std::cout<<"issuer: "<<str<<std::endl;
    110      OPENSSL_free (str);
    111    }
    112
    113    X509_free (server_certificate);
    114  } else {
    115    std::cout<<"Server does not have certificate. we sould Esc!"<<std::endl;
    116    return -1;
    117  }
    118
    119  ////////////////
    120  //  数据交换  //
    121  ////////////////
    122  char     buf [4096];
    123
    124  ret = SSL_write (ssl, "Hello World!", strlen("Hello World!"));  
    125  if( ret == -1 ) {
    126    std::cout<<"SSL_write error."<<std::endl;
    127    return -1;
    128  }
    129  ret = SSL_read (ssl, buf, sizeof(buf) - 1);  
    130  if( ret == -1 ) {
    131    std::cout<<"SSL_read error."<<std::endl;
    132    return -1;
    133  }
    134  buf[ret] = '';
    135  std::cout<<buf<<std::endl;
    136  SSL_shutdown(ssl);  /* send SSL/TLS close_notify */
    137  
    138  /////////////
    139  // Cleanup //
    140  /////////////
    141  closesocket(client_socket);
    142  SSL_free (ssl);
    143  SSL_CTX_free (ctx);
    144  WSACleanup();
    145  return 0;
    146}

    最后的输出结果:
    Server-Console:
    Connection from 16777343:20314
    SSL connection using: AES256-SHA
    Client does not have certificate.
    Hello World!


    Client-Console:
    SSL connection using: AES256-SHA
    Server certificate:
    subject: /C=cn/ST=shanghai/L=shanghai/O=shanghai/OU=shanghai/CN=shanghai/emailAd
    dress=ysong.lee@gmail.com
    issuer: /C=cn/ST=shanghai/L=shanghai/O=shanghai/OU=shanghai/CN=shanghai/emailAdd
    ress=ysong.lee@gmail.com
    I hear you.

  • 相关阅读:
    vue Can't resolve 图片
    TP-LINK WR740N中继设置,AP设置,设置后不能上网,亲测有效
    vue VSCode 开发设置(html自动补全、eslint保存时格式化、vetur 格式化html)
    不再手写import
    vscode vuter的快捷键 关键字
    prototype是什么?
    真有效值与有效值概念
    现代文经典
    古文经典
    最后,我想对你说一句:我爱你
  • 原文地址:https://www.cnblogs.com/xunbu7/p/4244881.html
Copyright © 2011-2022 走看看