openssl使用+Demo

时间:2023-03-09 20:19:31
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 Files\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat
e) 进入openssl路径 -> cd C:\devdiv\openssl-0.9.8i    (工作路径)
f) 创建Makefile文件: ms\do_ms     (出现%osversion% is not defined的错误忽略即可)
g) 编译动态库: nmake -f ms\ntdll.mak
   编译静态库: nmake -f ms\nt.mak

测试动态库: nmake -f ms\ntdll.mak test
   测试静态库: nmake -f ms\nt.mak test

安装动态库: nmake -f ms\ntdll.mak install
   安装静态库: nmake -f ms\nt.mak install

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

4. 配置文件在哪里?
C:\devdiv\openssl-0.9.8i\apps\openssl.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:

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

Client:

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

最后的输出结果:
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.