收藏 分享(赏)

OpenSSL编程实例.doc

上传人:HR专家 文档编号:11560796 上传时间:2020-06-24 格式:DOC 页数:19 大小:40.50KB
下载 相关 举报
OpenSSL编程实例.doc_第1页
第1页 / 共19页
OpenSSL编程实例.doc_第2页
第2页 / 共19页
OpenSSL编程实例.doc_第3页
第3页 / 共19页
OpenSSL编程实例.doc_第4页
第4页 / 共19页
OpenSSL编程实例.doc_第5页
第5页 / 共19页
点击查看更多>>
资源描述

1、客户端程序/ 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 10000const int nBufSize = 512;/ 初始化2.2版本Winsockint InitWinsock() WSADATA wsaData = 0; WORD wVe

2、r = MAKEWORD(2,2); int nRet = WSAStartup(wVer, &wsaData); if(nRet != 0) coutWinsock初始化失败,错误代码是nRetendl; return nRet;/ 创建一个套接字 SOCKET CreateSocket() SOCKET hSocket = INVALID_SOCKET; hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(hSocket = INVALID_SOCKET) int last_err = WSAGetLastError(); cou

3、t创建套接字失败,错误代码是last_errendl; 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

4、*)&saServer, sizeof(saServer); if(nRet = SOCKET_ERROR) int last_err = WSAGetLastError(); cout连接失败,错误代码是last_errendl; 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) / 作者所创建的客户端程序私匙

5、密码是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); couterr:X509_verify_cert_error_string(err)endl; return ok;SSL_CTX* InitSSLContext() cons

6、t 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加载客户端程序证书链失败endl; return NULL; SSL_CTX_set_default_passwd_cb(ctx, PasswordCB); / 加载客户端程序私匙文件 if(!SSL_CTX_use_PrivateKey_fi

7、le(ctx, ClientApp_PrivateKey.pem, SSL_FILETYPE_PEM) cout加载客户端程序私匙文件失败endl; return NULL; / 加载客户端程序所信任的CA if(!SSL_CTX_load_verify_locations(ctx, MyTestCA_Certificate.pem, NULL) cout加载客户端程序所信任的CA失败endl; return NULL; / 加载OpenSSL缺省信任的CA if(!SSL_CTX_set_default_verify_paths(ctx) cout 加载OpenSSL缺省信任的CA失败Ser

8、verCA-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 namebool Che

9、ckCertificate(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 buf256; if(X509_NAME_get_text_by_NID(subjectName, NID_commonName, buf, 256) 0 ) if(strcmp(buf, serverApp)

10、= 0) return true; return false;void DoWork(SSL* ssl) char buf256; while(true) if(!fgets(buf, sizeof(buf)/sizeof(buf0), stdin) SSL_shutdown(ssl); break; int len = strlen(buf); int nSent = 0; while(nSent len) int nRet = SSL_write(ssl, buf+nSent, len-nSent); if(nRet = 0) coutSSL_write发生错误endl; SSL_clea

11、r(ssl); break; nSent += nRet; int main(int argc, char* argv) if(InitWinsock() != 0) return -1; SOCKET hSocket = INVALID_SOCKET; SSL_CTX* ctx = NULL; SSL* ssl = NULL; BIO* sbio = NULL; int nRet = 0; try if(!InitOpenSSL() throw -1; ctx = InitSSLContext(); if(ctx = NULL) throw -1; ssl = SSL_new(ctx); h

12、Socket = CreateSocket(); if(hSocket = INVALID_SOCKET) throw -1; if(ConnectServer(hSocket) = SOCKET_ERROR) throw -1; sbio = BIO_new_socket(hSocket, BIO_NOCLOSE); SSL_set_bio(ssl, sbio, sbio); if(SSL_connect(ssl) = 0) coutSSL握手发生错误endl; throw -1; if(!CheckCertificate(ssl) throw -1; DoWork(ssl); catch(

13、int excpt_err) nRet = excpt_err; /if(sbio) BIO_free(sbio); if(ssl) SSL_free(ssl); if(ctx) SSL_CTX_free(ctx); if(hSocket != INVALID_SOCKET) closesocket(hSocket); WSACleanup(); return 0; -服务器程序/ OpenSSLServer.cpp#include #include using namespace std;#pragma comment (lib, Ws2_32.lib)#include openssl/ss

14、l.h#pragma comment(lib, ssleay32.lib)#pragma comment(lib, libeay32.lib)#define SERVICE_PORT 10000const int nBufSize = 512;/ 初始化2.2版本Winsockint InitWinsock() WSADATA wsaData = 0; WORD wVer = MAKEWORD(2,2); int nRet = WSAStartup(wVer, &wsaData); if(nRet != 0) coutWinsock初始化失败,错误代码是nRetendl; return nRe

15、t;/ 创建一个套接字 SOCKET CreateSocket() SOCKET hSocket = INVALID_SOCKET; hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(hSocket = INVALID_SOCKET) int last_err = WSAGetLastError(); cout创建套接字失败,错误代码是last_errendl; return hSocket;/ 绑定和监听int BindListen(SOCKET hSocket) / 填充本地套接字地址 sockaddr_in saListen

16、= 0; saListen.sin_family = AF_INET; saListen.sin_port = htons(SERVICE_PORT); saListen.sin_addr.s_addr = htonl(INADDR_ANY); / 把本地套接字地址绑定到监听套接字 int nRet = bind(hSocket, (sockaddr*)&saListen, sizeof(sockaddr); if(nRet = SOCKET_ERROR) int last_err = WSAGetLastError(); cout绑定套接字失败,错误代码是last_errendl; else

17、 / 开始监听 nRet = listen(hSocket, 5); if(nRet = SOCKET_ERROR) int last_err = WSAGetLastError(); cout监听失败,错误代码是last_errendl; return nRet;/ 接收连接请求SOCKET AcceptRequest(SOCKET hSocket) sockaddr_in saClient = 0; int nSALen = sizeof(sockaddr); SOCKET hClientSocket = accept(hSocket, (sockaddr*)&saClient, &nSA

18、Len); if(hClientSocket = INVALID_SOCKET) int last_err = WSAGetLastError(); cout接受连接请求失败,错误代码是last_errendl; return hClientSocket;bool InitOpenSSL() if(!SSL_library_init() return false; SSL_load_error_strings(); return true;int PasswordCB(char *buf, int size, int flag, void *userdata) / 作者所创建的服务器程序私匙密

19、码是abcdefgh const char* pass = abcdefgh; 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); couterr:X509_verify_cert_error_string(err)endl; return ok;SSL_CTX* InitSSLContext() const

20、 SSL_METHOD *meth = NULL; SSL_CTX* ctx = NULL; meth = SSLv23_method(); ctx = SSL_CTX_new(meth); / 加载服务器程序证书链 if(!SSL_CTX_use_certificate_chain_file(ctx, serverAppChain.pem) cout加载服务器程序证书链失败endl; return NULL; SSL_CTX_set_default_passwd_cb(ctx, PasswordCB); / 加载服务器程序私匙文件 if(!SSL_CTX_use_PrivateKey_fil

21、e(ctx, ServerApp_PrivateKey.pem, SSL_FILETYPE_PEM) cout加载服务器程序私匙文件失败endl; return NULL; / 加载服务器程序所信任的CA if(!SSL_CTX_load_verify_locations(ctx, MyTestCA_Certificate.pem, NULL) cout加载服务器程序所信任的CA失败endl; return NULL; / 加载OpenSSL缺省信任的CA if(!SSL_CTX_set_default_verify_paths(ctx) cout 加载OpenSSL缺省信任的CA失败MyTe

22、stCA, / 所以可以明确验证深度是1,即只检查MyTestCA SSL_CTX_set_verify_depth(ctx, 1); / SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT要求客户端提供证书, / 如果不提供的话,则校验失败。VerifyCB用于输出OpenSSL / 握手过程中验证客户端证书链失败时的错误信息 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, VerifyCB); SSL_CTX_set_mode(ctx, SSL_MO

23、DE_AUTO_RETRY); return ctx;/ 简单的校验,仅检查common namebool 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 buf256; if(X509_NAME_get_text_by_NID(subjectName,

24、 NID_commonName, buf, 256) 0 ) if(strcmp(buf, ClientApp) = 0) return true; return false;void DoWork(SSL* ssl) char buf256; while(true) int nRead = SSL_read(ssl, buf, sizeof(buf)/sizeof(buf0) - 1); if(nRead = 0) if(SSL_get_shutdown(ssl) & SSL_RECEIVED_SHUTDOWN) SSL_shutdown(ssl); else SSL_clear(ssl);

25、 break; bufnRead = 0; coutbuf; int main(int argc, char* argv) if(InitWinsock() != 0) return -1; SOCKET hListenSocket = INVALID_SOCKET; SOCKET hClientSocket = INVALID_SOCKET; SSL_CTX* ctx = NULL; SSL* ssl = NULL; BIO* sbio = NULL; int nRet = 0; try if(!InitOpenSSL() throw -1; ctx = InitSSLContext();

26、if(ctx = NULL) throw -1; ssl = SSL_new(ctx); hListenSocket = CreateSocket(); if(hListenSocket = INVALID_SOCKET) throw -1; if(BindListen(hListenSocket) = SOCKET_ERROR) throw -1; hClientSocket = AcceptRequest(hListenSocket); if(hClientSocket = INVALID_SOCKET) throw -1; sbio = BIO_new_socket(hClientSoc

27、ket, BIO_NOCLOSE); SSL_set_bio(ssl, sbio, sbio); if(SSL_accept(ssl) = 0) coutSSL握手发生错误endl; throw -1; if(!CheckCertificate(ssl) throw -1; DoWork(ssl); catch(int excpt_err) nRet = excpt_err; /if(sbio) BIO_free(sbio); if(ssl) SSL_free(ssl); if(ctx) SSL_CTX_free(ctx); if(hClientSocket != INVALID_SOCKET) closesocket(hClientSocket); if(hListenSocket != INVALID_SOCKET) closesocket(hListenSocket); WSACleanup(); return 0;

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 网络科技 > 计算机原理

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报