《OpenSSL编程实例.doc》由会员分享,可在线阅读,更多相关《OpenSSL编程实例.doc(15页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、如有侵权,请联系网站删除,仅供学习与交流OpenSSL编程实例【精品文档】第 15 页客户端程序/ 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
2、InitWinsock() WSADATA wsaData = 0; WORD wVer = 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_SO
3、CKET) int last_err = WSAGetLastError(); cout创建套接字失败,错误代码是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); / 使用远程套接字地址连接
4、到服务器 int nRet = connect(hSocket, (SOCKADDR *)&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
5、, 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); couterr:X509_verify_cert_error_string(err)end
6、l; 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加载客户端程序证书链失败endl; return NULL; SSL_CTX_set_default_passwd_cb(ctx, PasswordCB);
7、/ 加载客户端程序私匙文件 if(!SSL_CTX_use_PrivateKey_file(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_v
8、erify_paths(ctx) cout 加载OpenSSL缺省信任的CA失败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)
9、; 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, NID_commonNam
10、e, buf, 256) 0 ) if(strcmp(buf, serverApp) = 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); i
11、f(nRet = 0) coutSSL_write发生错误endl; SSL_clear(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(c
12、tx = NULL) throw -1; ssl = SSL_new(ctx); hSocket = 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(!CheckCert
13、ificate(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(hSocket != INVALID_SOCKET) closesocket(hSocket); WSACleanup(); return 0;服务器程序/ OpenSSLServer.cpp#include #include using namespace std;#pragma comm
14、ent (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 wVer = MAKEWORD(2,2); int nRet = WSAStartup(wVer, &wsaData); if(nRet != 0) co
15、utWinsock初始化失败,错误代码是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(); cout创建套接字失败,错误代码是last_errendl; return hSocket;/ 绑定和监听int BindListen(SOCKET hS
16、ocket) / 填充本地套接字地址 sockaddr_in saListen = 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 = WSAGetLastErro
17、r(); cout绑定套接字失败,错误代码是last_errendl; else / 开始监听 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 = ac
18、cept(hSocket, (sockaddr*)&saClient, &nSALen); 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, in
19、t flag, void *userdata) / 作者所创建的服务器程序私匙密码是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; r
20、eturn 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, serverAppChain.pem) cout加载服务器程序证书链失败endl; return NULL; SSL_CTX_set_default_passwd_cb(ctx, PasswordCB); / 加载
21、服务器程序私匙文件 if(!SSL_CTX_use_PrivateKey_file(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_verif
22、y_paths(ctx) cout 加载OpenSSL缺省信任的CA失败MyTestCA, / 所以可以明确验证深度是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,
23、 VerifyCB); SSL_CTX_set_mode(ctx, SSL_MODE_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; i
24、f(X509_NAME_get_text_by_NID(subjectName, 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)
25、 SSL_shutdown(ssl); else SSL_clear(ssl); 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(!InitOpenS
26、SL() throw -1; ctx = InitSSLContext(); 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) thr
27、ow -1; sbio = BIO_new_socket(hClientSocket, 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;
限制150内