OpenSSL 在Windows 下的使用

// 服务端
#define WIN32_LEAN_AND_MEAN
#include <iostream>
#include <Windows.h>
#include <winsock2.h>


#include <openssl/rsa.h>       /* SSLeay stuff */
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>




#define SERVER_PORT    5003

// certificate & key 的存放路径
// Note: 必须是全路径, 否则SSL_CTX_use_certificate_file等函数
//       无法找到文件在windows平台上.
// How to:
// #privatekey.pem
// openssl.exe genrsa -out privatekey.pem 2048
// #cacert.pem
// openssl.exe req -new -x509 -key privatekey.pem -out cacert.pem -days 1095 -config openssl.cnf
//
#define SERVER_CERTIFICATE   "c:\\cacert.pem"    
#define SERVER_KEY           "c:\\privatekey.pem"

#pragma comment( lib, "ws2_32.lib" )
#pragma comment( lib, "libeay32.lib" )
#pragma comment( lib, "ssleay32.lib" )

int  main()
{
	
	// 初始化 //
	
	SSL_CTX* ctx;
	SSL_METHOD *meth;

	SSL_load_error_strings();
	SSLeay_add_ssl_algorithms();
	meth = (SSL_METHOD *)SSLv23_server_method(); 

	ctx = SSL_CTX_new (meth);
	if (!ctx) {
		ERR_print_errors_fp(stderr);
		std::cout<<"SSL_CTX_new error."<<std::endl;
		return -1;
	}

	if (SSL_CTX_use_certificate_file(ctx, SERVER_CERTIFICATE, SSL_FILETYPE_PEM) <= 0) {
		ERR_print_errors_fp(stderr);
		std::cout<<"SSL_CTX_use_certificate_file error."<<std::endl;
		return -1;
	}
	if (SSL_CTX_use_PrivateKey_file(ctx, SERVER_KEY, SSL_FILETYPE_PEM) <= 0) {
		ERR_print_errors_fp(stderr);
		std::cout<<"SSL_CTX_use_PrivateKey_file error."<<std::endl;
		return -1;
	}

	if (!SSL_CTX_check_private_key(ctx)) {
		ERR_print_errors_fp(stderr);
		std::cout<<"SSL_CTX_check_private_key error."<<std::endl;
		return -1;
	}

	///
	// 建立原始的TCP连接 //
	///
	WSADATA wsaData;
	SOCKET listen_socket;
	SOCKET accept_socket;
	struct sockaddr_in addr_server;
	struct sockaddr_in addr_client;
	int addr_client_len;

	int ret = WSAStartup( MAKEWORD(2, 2), &wsaData );
	if ( ret != 0 ) {
		std::cout<<"WSAStartup error."<<std::endl;
		return -1;
	}

	listen_socket = socket (AF_INET, SOCK_STREAM, 0);  
	if( listen_socket == INVALID_SOCKET  ) {
		std::cout<<"socket error."<<std::endl;
		return -1;
	}

	memset (&addr_server, 0, sizeof(addr_server));
	addr_server.sin_family           = AF_INET;
	addr_server.sin_addr.S_un.S_addr = INADDR_ANY;
	addr_server.sin_port             = htons (SERVER_PORT);        

	ret = bind(listen_socket, (struct sockaddr*)&addr_server, sizeof(addr_server) ); 
	if( ret == SOCKET_ERROR )  {
		std::cout<<"bind error."<<std::endl;
		return -1;
	}

	ret = listen (listen_socket, 5); 
	if( ret == SOCKET_ERROR ) {
		std::cout<<"listen error."<<std::endl;
		return -1;
	}

	addr_client_len = sizeof(addr_client);
	accept_socket = accept (listen_socket, (struct sockaddr*) &addr_client, &addr_client_len);
	if( accept_socket == INVALID_SOCKET  ) {
		std::cout<<"accept error."<<std::endl;
		return -1;
	}
	closesocket(listen_socket);
	std::cout<<" Connection from "<<addr_client.sin_addr.S_un.S_addr<<":"<<addr_client.sin_port<<std::	endl;

	/
	// TCP连接已经建立,执行Server SSL //
	/
	SSL*     ssl;
	X509*    client_certificate;
	char*    str;

	ssl = SSL_new (ctx);                           
	if( ssl == NULL ) {
		std::cout<<"SSL_new error."<<std::endl;
		return -1;
	} 
	SSL_set_fd (ssl, accept_socket);
	ret = SSL_accept (ssl);                     
	if( ret == -1 ) {
		std::cout<<"SSL_accept error."<<std::endl;
		return -1;
	}

	// 获取cipher
	std::cout<<"SSL connection using: "<<SSL_get_cipher(ssl)<<std::endl;

	// 获取客户端的证书
	client_certificate = SSL_get_peer_certificate (ssl);
	if (client_certificate != NULL) {
		std::cout<<"Client certificate:"<<std::endl;

		str = X509_NAME_oneline (X509_get_subject_name (client_certificate), 0, 0);
		if( str == NULL ) {
			std::cout<<"X509_NAME_oneline error."<<std::endl;
		} else {
			std::cout<<"subject: "<<str<<std::endl;
			OPENSSL_free (str);
		}

		str = X509_NAME_oneline (X509_get_issuer_name  (client_certificate), 0, 0);
		if( str == NULL ) {
			std::cout<<"X509_NAME_oneline error."<<std::endl;
		} else {
			std::cout<<"issuer: "<<str<<std::endl;
			OPENSSL_free (str);
		}

		X509_free (client_certificate);
	} else {
		std::cout<<"Client does not have certificate. "<<std::endl;
	}

	
	//  数据交换  //
	
	char     buf [4096];

	ret = SSL_read (ssl, buf, sizeof(buf) - 1);    
	if( ret == -1 ) {
		std::cout<<"SSL_read error."<<std::endl;
		return -1;
	}
	buf[ret] = '\0';
	std::cout<<buf<<std::endl;

	ret = SSL_write (ssl, "I hear you.", strlen("I hear you.")); 
	if( ret == -1 ) {
		std::cout<<"SSL_write error."<<std::endl;
		return -1;
	}

	/
	// Cleanup //
	/
	closesocket(accept_socket);
	SSL_free (ssl);
	SSL_CTX_free (ctx);
	WSACleanup();
	return 0;
}


//客户端

#define WIN32_LEAN_AND_MEAN
#include <iostream>
#include <winsock2.h>

#include <openssl/rsa.h>       /* SSLeay stuff */
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>




#define SERVER_IP      "127.0.0.1"
#define SERVER_PORT    5003

#pragma comment( lib, "ws2_32.lib" )
#pragma comment( lib, "libeay32.lib" )
#pragma comment( lib, "ssleay32.lib" )


int main()
{
	int ret;
	
	// 初始化 //
	
	SSL_CTX* ctx;
	SSL_METHOD *meth;

	SSL_load_error_strings();
	SSLeay_add_ssl_algorithms();
	meth = (SSL_METHOD *)SSLv23_client_method();

	ctx = SSL_CTX_new (meth);
	if (!ctx) {
		ERR_print_errors_fp(stderr);
		std::cout<<"SSL_CTX_new error."<<std::endl;
		return -1;
	}

	///
	// 建立原始的TCP连接 //
	///
	WSADATA wsaData;
	SOCKET client_socket;
	struct sockaddr_in addr_server;

	ret = WSAStartup( MAKEWORD(2, 2), &wsaData );
	if ( ret != 0 ) {
		std::cout<<"WSAStartup error."<<std::endl;
		return -1;
	}
	client_socket = socket (AF_INET, SOCK_STREAM, 0);  
	if( client_socket == INVALID_SOCKET  ) {
		std::cout<<"socket error."<<std::endl;
		return -1;
	}

	memset (&addr_server, 0, sizeof(addr_server));
	addr_server.sin_family           = AF_INET;
	addr_server.sin_addr.S_un.S_addr = inet_addr(SERVER_IP);
	addr_server.sin_port             = htons (SERVER_PORT);

	ret = connect(client_socket, (struct sockaddr*) &addr_server, sizeof(addr_server)); 
	if( client_socket == SOCKET_ERROR  ) {
		std::cout<<"connect error."<<std::endl;
		return -1;
	}

	/
	// TCP连接已经建立,执行Client SSL //
	/
	SSL*     ssl;
	X509*    server_certificate;
	char*    str;

	ssl = SSL_new (ctx);                         
	if( ssl == NULL ) {
		std::cout<<"SSL_new error."<<std::endl;
		return -1;
	} 
	SSL_set_fd (ssl, client_socket);
	ret = SSL_connect (ssl);                     
	if( ret == -1 ) {
		std::cout<<"SSL_accept error."<<std::endl;
		return -1;
	}

	// 接下来的获取密码和获取服务器端证书的两部是可选的,不会影响数据交换

	// 获取cipher
	std::cout<<"SSL connection using: "<<SSL_get_cipher(ssl)<<std::endl;

	// 获取服务器端的证书
	server_certificate = SSL_get_peer_certificate (ssl);       
	if( server_certificate != NULL ) {
		std::cout<<"Server certificate:"<<std::endl;

		str = X509_NAME_oneline (X509_get_subject_name (server_certificate),0,0);
		if( str == NULL ) {
			std::cout<<"X509_NAME_oneline error."<<std::endl;
		} else {
			std::cout<<"subject: "<<str<<std::endl;
			OPENSSL_free (str);
		}

		str = X509_NAME_oneline (X509_get_issuer_name  (server_certificate),0,0);
		if( str == NULL ) {
			std::cout<<"X509_NAME_oneline error."<<std::endl;
		} else {
			std::cout<<"issuer: "<<str<<std::endl;
			OPENSSL_free (str);
		}

		X509_free (server_certificate);
	} else {
		std::cout<<"Server does not have certificate. we sould Esc!"<<std::endl;
		return -1;
	}

	
	//  数据交换  //
	
	char     buf [4096];

	ret = SSL_write (ssl, "Hello World!", strlen("Hello World!"));  
	if( ret == -1 ) {
		std::cout<<"SSL_write error."<<std::endl;
		return -1;
	}
	ret = SSL_read (ssl, buf, sizeof(buf) - 1);  
	if( ret == -1 ) {
		std::cout<<"SSL_read error."<<std::endl;
		return -1;
	}
	buf[ret] = '\0';
	std::cout<<buf<<std::endl;
	SSL_shutdown(ssl);  /* send SSL/TLS close_notify */

	/
	// Cleanup //
	/
	closesocket(client_socket);
	SSL_free (ssl);
	SSL_CTX_free (ctx);
	WSACleanup();
	return 0;
}




原文: http://www.cppblog.com/woomsg/archive/2008/11/03/64508.html



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值