OpenSSL编程实例.doc
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
客户端程序
// OpenSSLClient.cpp
#include
#include
using namespace std;
#pragma comment (lib, "Ws2_32.lib")
#include "openssl/ssl.h"
#pragma comment(lib, "ssleay32.lib")
#pragma comment(lib, "libeay32.lib")
#define SERVICE_PORT 10000
const int nBufSize = 512;
// 初始化2.2版本Winsock
int InitWinsock(){
WSADATA wsaData = {0};
WORD wVer = MAKEWORD(2,2);
int nRet = WSAStartup(wVer, &wsaData);
if(nRet != 0){
cout<<"Winsock初始化失败,错误代码是"< } return nRet; } // 创建一个套接字 SOCKET CreateSocket(){ SOCKET hSocket = INVALID_SOCKET; hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(hSocket == INVALID_SOCKET){ int last_err = WSAGetLastError(); cout<<"创建套接字失败,错误代码是"< } return hSocket; } // 连接到服务器 int ConnectServer(SOCKET hSocket){ // 填充远程套接字地址 SOCKADDR_IN saServer = {0}; saServer.sin_family = AF_INET; saServer.sin_port = htons(SERVICE_PORT); saServer.sin_addr.s_addr = inet_addr("127.0.0.1"); // 使用远程套接字地址连接到服务器 int nRet = connect(hSocket, (SOCKADDR *)&saServer, sizeof(saServer)); if(nRet == SOCKET_ERROR){ int last_err = WSAGetLastError(); cout<<"连接失败,错误代码是"< } return nRet; } bool InitOpenSSL(){ if(!SSL_library_init()) return false; SSL_load_error_strings(); return true; } int PasswordCB(char *buf, int size, int flag, void *userdata){ // 作者所创建的客户端程序私匙密码是12345678 const char* pass = "12345678"; if(size < strlen(pass) + 1) return(0); strcpy(buf, pass); return(strlen(pass)); } int VerifyCB(int ok, X509_STORE_CTX *store){ if(!ok){ int err = X509_STORE_CTX_get_error(store); cout< } return ok; } SSL_CTX* InitSSLContext(){ const SSL_METHOD *meth = NULL; SSL_CTX* ctx = NULL; meth = SSLv23_method(); ctx = SSL_CTX_new(meth); // 加载客户端程序证书链 if(!SSL_CTX_use_certificate_chain_file(ctx, "ClientAppChain.pem")){ cout<<"加载客户端程序证书链失败"< return NULL; } SSL_CTX_set_default_passwd_cb(ctx, PasswordCB); // 加载客户端程序私匙文件 if(!SSL_CTX_use_PrivateKey_file(ctx, "ClientApp_PrivateKey.pem", SSL_FILETYPE_PEM)){ cout<<"加载客户端程序私匙文件失败"< return NULL; } // 加载客户端程序所信任的CA if(!SSL_CTX_load_verify_locations(ctx, "MyTestCA_Certificate.pem", NULL)){ cout<<"加载客户端程序所信任的CA失败"< return NULL; } // 加载OpenSSL缺省信任的CA if(!SSL_CTX_set_default_verify_paths(ctx)){ cout<<" 加载OpenSSL缺省信任的CA失败"< return NULL; } // 我们知道,服务器的证书链是serverApp-->ServerCA-->MyTestCA, // 所以可以明确验证深度是2,即最多检查ServerCA和MyTestCA两个CA SSL_CTX_set_verify_depth(ctx, 2); // SSL_VERIFY_PEER要求服务器提供证书,VerifyCB用于输出OpenSSL // 握手过程中验证服务器证书链失败时的错误信息 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, VerifyCB); SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); return ctx; } // 简单的校验,仅检查common name bool CheckCertificate(SSL* ssl){ X509* cert = SSL_get_peer_certificate(ssl); if(cert == NULL) return false; X509_NAME* subjectName = X509_get_subject_name(cert); if(subjectName == NULL) return false; char buf[256];