OpenSSL编程实例.doc

合集下载

OpenSSL编程实例

OpenSSL编程实例

客户端程序// OpenSSLClient、cpp#include <winsock2、h>#include <iostream>using namespace std;#pragma ment (lib, "Ws2_32、lib")#include "openssl/ssl、h"#pragma ment(lib, "ssleay32、lib")#pragma ment(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){cout<<"Winsock初始化失败,错误代码就是"<<nRet<<endl; }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_err<<endl;}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<<"连接失败,错误代码就是"<<last_err<<endl;}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){// 作者所创建得客户端程序私匙密码就是12345678const 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<<err<<":"<<X509_verify_cert_error_string(err)<<endl;}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_, "ClientAppChain、pem")){cout<<"加载客户端程序证书链失败"<<endl;return NULL;}SSL_CTX_set_default_passwd_cb(ctx, PasswordCB);// 加载客户端程序私匙文件if(!SSL_CTX_use_PrivateKey_, "ClientApp_PrivateKey、pem",SSL_)){cout<<"加载客户端程序私匙文件失败"<<endl;return NULL;}// 加载客户端程序所信任得CAif(!SSL_CTX_load_verify_locations(ctx, "MyTestCA_Certificate、pem",NULL)){cout<<"加载客户端程序所信任得CA失败"<<endl;return NULL;}// 加载OpenSSL缺省信任得CAif(!SSL_CTX_set_default_verify_paths(ctx)){cout<<" 加载OpenSSL缺省信任得CA失败"<<endl;return NULL;}// 我们知道,服务器得证书链就是serverApp-->ServerCA-->MyTestCA,// 所以可以明确验证深度就是2,即最多检查ServerCA与MyTestCA两个CASSL_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;}// 简单得校验,仅检查mon 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 buf[256];if(X509_NAME_get_text_by_NID(subjectName, NID_monName, buf, 256) >0 ){if(strcmp(buf, "serverApp") == 0)return true;}}void DoWork(SSL* ssl){char buf[256];while(true){if(!fgets(buf, sizeof(buf)/sizeof(buf[0]), 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){cout<<"SSL_write发生错误"<<endl;SSL_clear(ssl);break;}nSent += nRet;}}}int main(int argc, char* argv[]){if(InitWinsock() != 0)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);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){cout<<"SSL握手发生错误"<<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(hSocket != INVALID_SOCKET)closesocket(hSocket);WSACleanup();return 0;}----------------------------------------------------服务器程序// OpenSSLServer、cpp#include <winsock2、h>#include <iostream>using namespace std;#pragma ment (lib, "Ws2_32、lib")#include "openssl/ssl、h"#pragma ment(lib, "ssleay32、lib")#pragma ment(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){cout<<"Winsock初始化失败,错误代码就是"<<nRet<<endl; }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_err<<endl; }return hSocket;}// 绑定与监听int BindListen(SOCKET hSocket){// 填充本地套接字地址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 = WSAGetLastError();cout<<"绑定套接字失败,错误代码就是"<<last_err<<endl;}else{// 开始监听nRet = listen(hSocket, 5);if(nRet == SOCKET_ERROR){int last_err = WSAGetLastError();cout<<"监听失败,错误代码就是"<<last_err<<endl;}}return nRet;}// 接收连接请求SOCKET AcceptRequest(SOCKET hSocket){sockaddr_in saClient = {0};int nSALen = sizeof(sockaddr);SOCKET hClientSocket = accept(hSocket, (sockaddr*)&saClient, &nSALen);if(hClientSocket == INVALID_SOCKET){int last_err = WSAGetLastError();cout<<"接受连接请求失败,错误代码就是"<<last_err<<endl;}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){// 作者所创建得服务器程序私匙密码就是abcdefghconst 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);cout<<err<<":"<<X509_verify_cert_error_string(err)<<endl;}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_, "serverAppChain、pem")){cout<<"加载服务器程序证书链失败"<<endl;return NULL;}SSL_CTX_set_default_passwd_cb(ctx, PasswordCB);// 加载服务器程序私匙文件if(!SSL_CTX_use_PrivateKey_, "ServerApp_PrivateKey、pem",SSL_)){cout<<"加载服务器程序私匙文件失败"<<endl;return NULL;}// 加载服务器程序所信任得CAif(!SSL_CTX_load_verify_locations(ctx, "MyTestCA_Certificate、pem",NULL)){cout<<"加载服务器程序所信任得CA失败"<<endl;return NULL;}// 加载OpenSSL缺省信任得CAif(!SSL_CTX_set_default_verify_paths(ctx)){cout<<" 加载OpenSSL缺省信任得CA失败"<<endl;return NULL;}// 我们知道,客户端得证书链就是ClientApp-->MyTestCA,// 所以可以明确验证深度就是1,即只检查MyTestCASSL_CTX_set_verify_depth(ctx, 1);// SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT要求客户端提供证书,// 如果不提供得话,则校验失败。

openssl操作手册

openssl操作手册

OpenSSL 是一个开源的加密库,提供了各种加密算法、数字证书、SSL/TLS 协议等功能,被广泛用于网络安全和加密通信领域。

以下是OpenSSL 的一些常见用法和操作:1. 生成证书:使用OpenSSL 可以生成各种类型的数字证书,包括自签名证书、CA 证书、服务器证书、客户端证书等。

您可以使用OpenSSL 提供的命令行工具或API 接口来生成证书。

2. 加密和解密:OpenSSL 提供了各种加密算法,包括对称加密和非对称加密。

您可以使用OpenSSL 提供的命令行工具或API 接口来进行加密和解密操作。

3. 签名和验证:OpenSSL 提供了数字签名和验证的功能,可以用于保证数据的完整性和真实性。

您可以使用OpenSSL 提供的命令行工具或API 接口来进行签名和验证操作。

4. SSL/TLS 安全通信:OpenSSL 提供了SSL/TLS 协议的实现,可以用于安全通信。

您可以使用OpenSSL 提供的命令行工具或API 接口来实现SSL/TLS 安全通信。

5. 网络安全工具:OpenSSL 提供了各种网络安全工具,包括OpenSSL s_server、OpenSSL s_client、OpenSSL speed、OpenSSL rand 等。

这些工具可以用于测试和评估网络安全性能。

要使用OpenSSL,您需要安装OpenSSL 库,并包含相应的头文件。

在编写代码时,您可以调用OpenSSL 提供的函数和数据结构来实现您需要的加密、签名、SSL/TLS 安全通信等功能。

OpenSSL 提供了详细的文档和使用手册,您可以在OpenSSL 官方网站上找到完整的文档和参考手册。

在文档中,您可以找到各种函数的使用说明、示例代码和详细的接口说明,以帮助您更好地使用OpenSSL 库。

用openssl进行SSL编程

用openssl进行SSL编程
ssl_verify_none表示不验证,ssl_verify_peer用于客户端时要求服务器必须提供证书,用于服务器时服务器会发出证书请求消息要求客户端提供证书,但是客户端也可以不提供
ssl_verigy_fail_if_no_peer_cert只适用于服务器且必须提供证书。他必须与ssl_verify_peer一起使用
ssl_ctx_check_private_key(ctx);
设置一个临时的rsa,在出口算法中,有规定需要这么做的。
rsa *rsa=rsa_generate_key(512,rsa_f4,null,null);
ssl_ctx_set_tmp_rsa(ctx,rsa);
用于设置验证方式。s_server_verify是以下值的逻辑或
为了从自己本身的程序中产生一个session_id,所以要给本程序设定一个session_id_context,否则程序从外部获取session_id_context来得到session_id,那很容易产生错误
长度不能大于ssl_max_ssl_session_id_length
const unsigned char s_server_session_id_context[100]="1111asdfd";
这里主要set cert_store
char *cafile=null,*capath=null;
ssl_ctx_load_verify_locations(ctx,cafile,capath);
当需要客户端验证的时候,服务器把cafile里面的可信任ca证书发往客户端。
if(cafile !=null )ssl_ctx_set_client_ca_list(ctx,ssl_load_client_ca_file(cafile));

openssl3.0加密算法库编程精要05-详解EVPAPI公开密钥密码算法--生成密钥对

openssl3.0加密算法库编程精要05-详解EVPAPI公开密钥密码算法--生成密钥对

openssl3.0加密算法库编程精要05-详解EVPAPI公开密钥密码算法--⽣成密钥对5.1 公开密钥系统简介 公开密钥系统最早于上世纪 70 年代被发明。

在这种密码系统中,已知加密密钥,在现有计算机技术条件下很难快速求出解密密钥,这个推导过程耗费的计算机算⼒巨⼤到不切实际,所以加密密钥是可以公开的,所以这种系统被称为公开密钥系统。

公开密钥系统被⼴泛地⽤于各种密码协议、数字签名以及电⼦商务等各种领域中。

5.2 RSA 算法 公开密钥系统使⽤的算法最流⾏的当属 RSA 算法,它由 Ronald Rivest、Adi Shamir 和 Lenoard Adleman 于上世纪70 年代发明,该算法的安全性基于⼤数分解的难度,它的原理如下: 设:明⽂为P,密⽂为C,加密函数E(x),解密函数D(x); (1)⾸先选取⼀个公钥指数 e,同时⽣成两个⼤素数 p 和 q; (2)计算n=pq,同时计算欧拉函数ϕ(n)=ϕ(pq)=ϕ(p)ϕ(q)=(p−1)(q−1),确保当前公钥指数 e 和ϕ(n) 互素,那么 e 和 n 组成的数对 (e, n) 即为公钥; (3)加密过程为E(P)=C≡P e(mod n), 0⩽; (4)由于 e 和 n 互素,所以存在⼀个 e 的逆 d,使得ed \equiv 1 (mod \phi(n)) 成⽴,故解密时需要先解线 性同余⽅程求出 d; (5)求出 d 之后,解密过程则为D(C) = C^{d} = ( P^{e} )^{d} = P^{ed}; (6)由于ed \equiv 1 (mod \phi(n)) 成⽴,所以存在⼀个整数 k,使得等式ed = k\phi(n) + 1成⽴; (7)如果P和 n 互素,由欧拉定理得出,P^{\phi(ed)} \equiv P^{k\phi(n) + 1} \equiv PP^{k\phi(n)} \equiv P(mod n) (8)⼀般情况下,P和 n 不互素的概率极⼩,但是如果P和 n 不互素,那么由于P必然⼩于 n (如果 P > n,则⽆法通过解密算法计算出明⽂),p 和 q ⼜都是素数,那么 P必然符合以下的条件 P = ap或P = bq,同时P \neq kpq,a 和 b 为正整数,由于 p 和 q 为素数,所以有以下结论 如果P = ap,那么P和 q 互素; 如果P = bq,那么P和 p 互素; 所以我们假设P = ap,那么P和 q 互素,根据欧拉定理得 P^{\phi(q)} \equiv 1(mod q),然后有 (P^{\phi(q)})^{k\phi(p)} \equiv (1)^{k\phi(p)}(mod q) P^{k\phi(n)} \equiv 1(mod q),然后根据同余的定义可知,存在⼀个数 r,使得以下式⼦成⽴ P^{k\phi(n)} = 1 + rq,两边同时乘以P,得 P^{k\phi(n) + 1} = P + rqP,⼜因为P = ap,所以 P^{k\phi(n) + 1} = P + rqap,然后由于n = pq,所以 P^{k\phi(n) + 1} = P + ran,由于 r、a 是常量,所以最终得 P^{k\phi(n) + 1} \equiv P(mod n),进⼀步得到 P^{ed} \equiv P(mod n) 所以我们证明了使⽤ d 可以解密出加密数据,那么数对 (d,n) 即为私钥,但是原⽂P必须⼩于模数 n, 否则⽆法正确解密。

openssl编程 示例

openssl编程 示例

openssl编程示例以OpenSSL编程示例为标题的文章是关于如何使用OpenSSL库进行编程的。

OpenSSL是一个开源的加密工具包,提供了许多密码学功能,如加密、解密、签名和验证等。

在本文中,我将介绍OpenSSL 库的基本使用方法,并提供一些编程示例来帮助读者更好地理解。

OpenSSL是一个功能强大且广泛使用的加密库,可以用于开发各种应用程序,包括网络安全、数据传输和身份验证等。

它支持许多密码学算法,如对称加密算法(如AES和DES)、非对称加密算法(如RSA和ECC)以及哈希函数(如MD5和SHA-256)等。

在开始使用OpenSSL之前,我们需要安装OpenSSL库并配置开发环境。

安装OpenSSL库的具体方法因操作系统而异,可以在OpenSSL 官方网站上找到相关的安装指南。

配置开发环境主要包括设置编译器参数和链接库文件等。

一旦环境配置完成,我们就可以开始使用OpenSSL库进行编程了。

下面是一些常用的OpenSSL编程示例:1. 生成密钥对使用OpenSSL库生成非对称加密算法所需的密钥对是一个常见的操作。

以下是一个生成RSA密钥对的示例代码:```c#include <openssl/rsa.h>int main() {RSA* rsa = RSA_generate_key(2048, RSA_F4, NULL, NULL);if (rsa == NULL) {printf("Failed to generate RSA key pair\n");return -1;}// 打印公钥和私钥printf("Public Key:\n%s\n", BN_bn2hex(rsa->n));printf("Private Key:\n%s\n", BN_bn2hex(rsa->d));RSA_free(rsa);return 0;}```2. 加密和解密数据使用OpenSSL库进行数据加密和解密是保护数据安全的常见操作。

openssl简易文档

openssl简易文档

openssl简易文档一:编译前置工作:1.下载openssl.网址:/source/2.解压缩.3.下载activeperl,并安装.编译:用vs2005编译,编译之前要先根据配置生成makefile,具体为下面a,b,c三步:a.C:\OpenSSL\openssl-0.9.8&gt;Perl Configure VC-WIN32b.C:\OpenSSL\openssl1-0.9.8&gt;ms\do_ms.batc.C:\OpenSSL\openssl-0.9.8&gt;nmake -f ms\ntdll.mak编译选项:我们必须在生成makefile前使得openssl得到正确配置,方法就是在Perl Configure VC-WIN32命令行加入编译选项,具体为:Perl Configure VC-WIN32 XXX,其中XXX为下列三大类全局选项第一类是全局性选项:zlibzlib-dynamicno-zlib使用静态的zlib压缩库、使用动态的zlib压缩库、不使用zlib压缩功能。

threadsno-threads是否编译支持多线程的库。

默认支持。

sharedno-shared是否生成动态连接库。

(重点)enable-sse2no-sse2启用/禁用SSE2指令集加速。

如果你的CPU支持SSE2指令集,就可以打开,否则就要关闭。

gmpno-gmp启用/禁用GMP库rfc3779no-rfc3779启用/禁用实现X509v3证书的IP地址扩展krb5no-krb5启用/禁用Kerberos 5 支持sslno-sslssl2ssl3no-ssl2no-ssl3tlsno-tls 启用/禁用SSL(包含了SSL2/SSL3) TLS 协议支持。

算法选项可选的目录如下:no-md2,no-md4,no-mdc2,no-ripemd这些都是摘要算法,含义一目了然。

openssl使用方式

openssl使用方式

openssl使用方式
摘要:
1.OpenSSL 简介
2.OpenSSL 的使用方式
3.示例:使用OpenSSL 进行加密和解密
4.小结
正文:
OpenSSL 是一个安全套接字层(SSL)和传输层安全(TLS)协议的开源加密库,广泛应用于互联网的安全通信。

它支持多种加密算法、数字签名、证书管理等功能,为网络应用程序提供了安全的通信功能。

OpenSSL 的使用方式主要分为以下几个步骤:
1.安装OpenSSL 库:首先,你需要在你的计算机或服务器上安装OpenSSL 库。

在Linux 系统中,可以使用“sudo apt-get install openssl”命令进行安装。

在Windows 系统中,可以通过访问OpenSSL 官网下载相应版本的安装包进行安装。

2.配置OpenSSL:安装完成后,你需要对OpenSSL 进行配置,以便它能够正确地为你的应用程序提供服务。

配置过程包括设置加密算法、生成密钥和证书等。

具体的配置方法可以参考OpenSSL 的官方文档。

3.初始化OpenSSL:在应用程序中,你需要使用OpenSSL 的API 对SSL/TLS 连接进行初始化。

这一步通常包括创建一个SSL/TLS 上下文、初始化一个SSL/TLS 连接等。

4.加密和解密数据:在数据传输过程中,你需要使用OpenSSL 的API 对数据进行加密和解密。

加密过程中,你需要使用SSL/TLS 上下文和密钥对数据进行加密;解密过程中,你需要使用SSL/TLS 上下文和相应的私钥对数据进行解密。

openssl的man中文文档

openssl的man中文文档

openssl的man中文文档发信站: BBS 水木清华站 (Fri Nov 10 20:19:30 2000) [/b:631992e780]不久前接到有关ssl的活,结果找遍中文网站资料实在奇缺。

感觉是好象现在国内做这个技术的人不多所有有兴趣写点东西来介绍一下。

我使用的ssl的toolkit是openssl就用openssl做例子来讲解openssl实在太大了,指令也多,API也多,更严重的是它的API没有说明。

我打算漫漫说清楚其主要指令的用法,主要API的中文说明,以及使用/编程的方法。

工作量很大,因为我接触它也没几个月,现在大概完成了1/10吧,先把目前自己的一些心得,找到的资料和一些翻译出来的东西贴出来,希望对研究ssl的人有帮助openssl简介-证书/forum/viewtopic.php?p=3161562#3161585openssl简介-加密算法/forum/viewtopic.php?p=3161562#3161685openssl简介-协议/forum/viewtopic.php?p=3161562#3161727openssl简介-入门/forum/viewtopic.php?p=3161562#3162073openssl简介-指令 verify/forum/viewtopic.php?p=3161562#3173096openssl简介-指令asn1parse/forum/viewtopic.php?p=3161562#3173120 openssl简介-指令ca/forum/viewtopic.php?p=3173126#3173126openssl简介-指令cipher/forum/viewtopic.php?p=3173132#3173132 openssl简介-指令dgst/forum/viewtopic.php?p=3173136#3173136openssl简介-指令dhparam/forum/viewtopic.php?p=3173142#3173142openssl简介-指令enc/forum/viewtopic.php?p=3173146#3173146openssl简介-指令gendsa/forum/viewtopic.php?p=3173149#3173149openssl简介-指令genrsa/forum/viewtopic.php?p=3173152#3173152openssl简介-指令passwd/forum/viewtopic.php?p=3173154#3173154openssl简介-指令pkcs7/forum/viewtopic.php?p=3173156#3173156openssl简介-指令rand/forum/viewtopic.php?p=3173158#3173158openssl简介-指令req/forum/viewtopic.php?p=3173162#3173162openssl简介-指令rsa/forum/viewtopic.php?p=3173164#3173164openssl简介-指令rsautl/forum/viewtopic.php?p=3173168#3173168 openssl简介-指令s_client/forum/viewtopic.php?p=3173171#3173171openssl简介-指令s_server/forum/viewtopic.php?p=3173175#3173175openssl简介-指令sess_id/forum/viewtopic.php?p=3173176#3173176openssl简介-指令speed/forum/viewtopic.php?p=3173178#3173178openssl简介-指令version/forum/viewtopic.php?p=3173181#3173181openssl简介-指令x509/forum/viewtopic.php?p=3173188#3173188wingger 回复于:2005-01-07 09:29:51[b:2f84c104e9]标题:openssl简介--证书[/b:2f84c104e9][b:2f84c104e9]发信站:BBS水木清华站(FriNov1020:29:282000)引用请指明原作译者fordesign@二证书[/b:2f84c104e9]证书就是数字化的文件,里面有一个实体(网站,个人等)的公共密钥和其他的属性,如名称等。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

客户端程序// OpenSSLClient.cpp#include <winsock2.h>#include <iostream>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 wVer = MAKEWORD(2,2);int nRet = WSAStartup(wVer, &wsaData);if(nRet != 0){cout<<"Winsock初始化失败,错误代码是"<<nRet<<endl;}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_err<<endl;}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<<"连接失败,错误代码是"<<last_err<<endl;}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){// 作者所创建的客户端程序私匙密码是12345678const 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<<err<<":"<<X509_verify_cert_error_string(err)<<endl;}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);// 加载客户端程序私匙文件if(!SSL_CTX_use_PrivateKey_file(ctx, "ClientApp_PrivateKey.pem",SSL_FILETYPE_PEM)){cout<<"加载客户端程序私匙文件失败"<<endl;return NULL;}// 加载客户端程序所信任的CAif(!SSL_CTX_load_verify_locations(ctx, "MyTestCA_Certificate.pem",NULL)){cout<<"加载客户端程序所信任的CA失败"<<endl;return NULL;}// 加载OpenSSL缺省信任的CAif(!SSL_CTX_set_default_verify_paths(ctx)){cout<<" 加载OpenSSL缺省信任的CA失败"<<endl;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 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 buf[256];if(X509_NAME_get_text_by_NID(subjectName, NID_commonName, buf, 256) >0 ){if(strcmp(buf, "serverApp") == 0)return true;}return false;}void DoWork(SSL* ssl){char buf[256];while(true){if(!fgets(buf, sizeof(buf)/sizeof(buf[0]), 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){cout<<"SSL_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(ctx == 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){cout<<"SSL握手发生错误"<<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(hSocket != INVALID_SOCKET)closesocket(hSocket);WSACleanup();return 0;}----------------------------------------------------服务器程序// OpenSSLServer.cpp#include <winsock2.h>#include <iostream>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 wVer = MAKEWORD(2,2);int nRet = WSAStartup(wVer, &wsaData);if(nRet != 0){cout<<"Winsock初始化失败,错误代码是"<<nRet<<endl;}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_err<<endl;}return hSocket;}// 绑定和监听int BindListen(SOCKET hSocket){// 填充本地套接字地址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 = WSAGetLastError();cout<<"绑定套接字失败,错误代码是"<<last_err<<endl;}else{// 开始监听nRet = listen(hSocket, 5);if(nRet == SOCKET_ERROR){int last_err = WSAGetLastError();cout<<"监听失败,错误代码是"<<last_err<<endl;}}return nRet;}// 接收连接请求SOCKET AcceptRequest(SOCKET hSocket){sockaddr_in saClient = {0};int nSALen = sizeof(sockaddr);SOCKET hClientSocket = accept(hSocket, (sockaddr*)&saClient, &nSALen);if(hClientSocket == INVALID_SOCKET){int last_err = WSAGetLastError();cout<<"接受连接请求失败,错误代码是"<<last_err<<endl;}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){// 作者所创建的服务器程序私匙密码是abcdefghconst 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);cout<<err<<":"<<X509_verify_cert_error_string(err)<<endl;}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, "serverAppChain.pem")){cout<<"加载服务器程序证书链失败"<<endl;return NULL;}SSL_CTX_set_default_passwd_cb(ctx, PasswordCB);// 加载服务器程序私匙文件if(!SSL_CTX_use_PrivateKey_file(ctx, "ServerApp_PrivateKey.pem",SSL_FILETYPE_PEM)){cout<<"加载服务器程序私匙文件失败"<<endl;return NULL;}// 加载服务器程序所信任的CAif(!SSL_CTX_load_verify_locations(ctx, "MyTestCA_Certificate.pem",NULL)){cout<<"加载服务器程序所信任的CA失败"<<endl;return NULL;}// 加载OpenSSL缺省信任的CAif(!SSL_CTX_set_default_verify_paths(ctx)){cout<<" 加载OpenSSL缺省信任的CA失败"<<endl;return NULL;}// 我们知道,客户端的证书链是ClientApp-->MyTestCA,// 所以可以明确验证深度是1,即只检查MyTestCASSL_CTX_set_verify_depth(ctx, 1);// SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT要求客户端提供证书,// 如果不提供的话,则校验失败。

相关文档
最新文档