基于openssl实现的安全连接

合集下载

利用openssl命令进行加密和证书操作

利用openssl命令进行加密和证书操作

利用openssl命令进行加密和证书操作一、利用 OpenSSL 命令进行加密和证书操作OpenSSL 是一个开放源代码的软件库,可提供用于传输层安全性(TLS) 和安全套接字层 (SSL) 协议的加密功能,以及用于生成数字证书的工具。

本文将介绍如何使用 OpenSSL 命令进行加密和证书操作。

二、加密文件1. 创建密钥对使用 OpenSSL 命令生成密钥对,其中包括一个私钥和一个公钥。

```bashopenssl genpkey -algorithm RSA -out private.key```这将生成一个名为 private.key 的私钥文件。

```bashopenssl rsa -pubout -in private.key -out public.key```这将从私钥文件中提取公钥,并将其保存为 public.key。

2. 加密文件使用公钥对文件进行加密。

```bashopenssl rsautl -encrypt -in plaintext.txt -inkey public.key -pubin -out ciphertext.enc```其中,plaintext.txt 是待加密的文件,ciphertext.enc 是加密后的文件。

3. 解密文件使用私钥对加密文件进行解密。

```bashopenssl rsautl -decrypt -in ciphertext.enc -inkey private.key -out decrypted.txt```其中,ciphertext.enc 是待解密的文件,decrypted.txt 是解密后的文件。

三、生成自签名证书1. 创建私钥使用 OpenSSL 命令生成私钥。

```bashopenssl genpkey -algorithm RSA -out private.key```2. 创建证书请求使用私钥生成证书请求。

```bashopenssl req -new -key private.key -out request.csr```在生成过程中,您需要提供一些证书请求的相关信息。

利用OpenSSL库对Socket传输进行安全加密(RSA+AES)

利用OpenSSL库对Socket传输进行安全加密(RSA+AES)

利⽤OpenSSL库对Socket传输进⾏安全加密(RSA+AES)轉⾃:/uid-9543173-id-3921143.html利⽤OpenSSL库对Socket传输进⾏安全加密(RSA+AES)1. 利⽤RSA安全传输AES⽣成密钥所需的Seed(32字节)2. 利⽤AES_encrypt/AES_decrypt对Socket上⾯的业务数据进⾏AES加密/解密理论上只需要AES就能保证全部流程,但由于AES加密所需要的AES-KEY是⼀个结构。

这个⼀个结构,如果通过⽹络进⾏传输,就需要对它进⾏⽹络编码,OpenSSL⾥⾯没有现成的API所以就引⼊RSA来完成⾸次安全的传输,保证Seed不会被窃听。

同样,只使⽤RSA也能完成全部流程,但由于RSA的处理效率⽐AES低,所以在业务数据传输加密上还是使⽤AES下⾯的代码包含了上述传输加密流程所需的所有步骤(OpenSSL部分)在实际的Socket应⽤开发时,需要将这些步骤插⼊到Client/Server⽹络通信的特定阶段所需的OpenSSL主要的API及功能描述1. RSA_generate_key() 随机⽣成⼀个RSA密钥对,供RSA加密/解密使⽤2. i2d_RSAPublicKey() 将RSA密钥对⾥⾯的公钥提出到⼀个BUF,⽤于⽹络传输给对⽅3. d2i_RSAPublicKey() 将从⽹络传过来的公钥信息⽣成⼀个加密使⽤的RSA(它⾥⾯只有公钥)4. RSA_public_encrypt() 使⽤RSA的公钥对数据进⾏加密5. RSA_private_decrypt() 使⽤RSA的私钥对数据进⾏解密6. AES_set_encrypt_key() 根据Seed⽣成AES密钥对中的加密密钥7. AES_set_decrypt_key() 根据Seed⽣成AES密钥对中的解密密钥8. AES_encrypt() 使⽤AES加密密钥对数据进⾏加密9. AES_decrypt() 使⽤AES解密密钥对数据进⾏解密⼀个典型的安全Socket的建⽴流程, 其实就是如何将Server随机Seed安全发给ClientC: Client S:ServerC: RSA_generate_key() --> RSAKey --> i2d_RSAPublicKey(RSAKey) --> RSAPublicKeyC: Send(RSAPublicKey) TO ServerS: Recv() --> RSAPublicKey --> d2i_RSAPublicKey(RSAPublicKey) --> RSAKeyS: Rand() --> Seed --> RSA_public_encrypt(RSAKey, Seed) --> EncryptedSeedS: Send(EncryptedSeed) TO ClientC: Recv() --> EncryptedSeed --> RSA_private_decrypt(RSAKey, EncryptedSeed) --> Seed--- 到此, Client和Server已经完成完成传输Seed的处理--- 后⾯的流程是它们怎样使⽤这个Seed来进⾏业务数据的安全传输C: AES_set_encrypt_key(Seed) --> AESEncryptKeyC: AES_set_decrypt_key(Seed) --> AESDecryptKeyS: AES_set_encrypt_key(Seed) --> AESEncryptKeyS: AES_set_decrypt_key(Seed) --> AESDecryptKey--- Client传输数据给ServerC: AES_encrypt(AESEncryptKey, Data) --> EncryptedData --> Send() --> ServerS: Recv() --> EncryptedData --> AES_decrypt(AESDecryptKey, EncryptedData) --> Data--- Server传输数据给ClientS: AES_encrypt(AESEncryptKey, Data) --> EncryptedData --> Send() --> ClientC: Recv() --> EncryptedData --> AES_decrypt(AESDecryptKey, EncryptedData) --> Data流程图如下:相关的代码实现如下:#include <string.h>#include <openssl/rsa.h>#include <openssl/aes.h>int main(){// 1. 产⽣RSA密钥对// 产⽣512字节公钥指数为RSA_F4的密钥对,公钥指数有RSA_F4和RSA_3两种// 我不清楚它们的区别,就随便选定RSA_F4// 可以使⽤RSA_print_fp()看看RSA⾥⾯的东西RSA *ClientRsa = RSA_generate_key(512, RSA_F4, NULL, NULL);// ---------// 2. 从RSA结构中提取公钥到BUFF,以便将它传输给对⽅// 512位的RSA其公钥提出出来长度是74字节,⽽私钥提取出来有超过300字节// 为保险起见,建议给它们预留⼀个512字节的空间unsigned char PublicKey[512];unsigned char *PKey = PublicKey; // 注意这个指针不是多余,是特意要这样做的,int PublicKeyLen = i2d_RSAPublicKey(ClientRsa, &PKey);// 不能采⽤下⾯的⽅法,因为i2d_RSAPublicKey()会修改PublicKey的值// 所以要引⼊PKey,让它作为替死⿁// unsigned char *PublicKey = (unsigned char *)malloc(512);// int PublicKeyLen = i2d_RSAPublicKey(ClientRsa, &PublicKey);// 逐个字节打印PublicKey信息printf("PublicKeyBuff, Len=%d\n", PublicKeyLen);for (int i=0; i<PublicKeyLen; i++){printf("0x%02x, ", *(PublicKey+i));}printf("\n");// ---------// 3. 跟据上⾯提出的公钥信息PublicKey构造⼀个新RSA密钥(这个密钥结构只有公钥信息)PKey = PublicKey;RSA *EncryptRsa = d2i_RSAPublicKey(NULL, (const unsigned char**)&PKey, PublicKeyLen);// ---------// 4. 使⽤EncryptRsa加密数据,再使⽤ClientRsa解密数据// 注意, RSA加密/解密的数据长度是有限制,例如512位的RSA就只能最多能加密解密64字节的数据// 如果采⽤RSA_NO_PADDING加密⽅式,512位的RSA就只能加密长度等于64的数据// 这个长度可以使⽤RSA_size()来获得unsigned char InBuff[64], OutBuff[64];strcpy((char *)InBuff, "1234567890abcdefghiklmnopqrstuvwxyz.");RSA_public_encrypt(64, (const unsigned char*)InBuff, OutBuff, EncryptRsa, RSA_NO_PADDING); // 加密 memset(InBuff, 0, sizeof(InBuff));RSA_private_decrypt(64, (const unsigned char*)OutBuff, InBuff, ClientRsa, RSA_NO_PADDING); // 解密 printf("RSADecrypt OK: %s \n", InBuff);// ----------// 5. 利⽤随机32字节Seed来产⽣256位的AES密钥对unsigned char Seed[32]; // 可以采⽤Rand()等⽅法来构造随机信息AES_KEY AESEncryptKey, AESDecryptKey;AES_set_encrypt_key(Seed, 256, &AESEncryptKey);AES_set_decrypt_key(Seed, 256, &AESDecryptKey);// ----------// 6. 使⽤AES密钥对来加密/解密数据// 注意,256位的AES密钥只能加密/解密16字节长的数据strcpy((char *)InBuff, "a1b2c3d4e5f6g7h8?");AES_encrypt(InBuff, OutBuff, &AESEncryptKey);memset(InBuff, 0, sizeof(InBuff));AES_decrypt(OutBuff, InBuff, &AESDecryptKey);printf("AESDecrypt OK: %s \n", InBuff);// ----------// 7. 谨记要释放RSA结构RSA_free(ClientRsa);RSA_free(EncryptRsa);return(0);}。

ssl_connect函数原理

ssl_connect函数原理

ssl_connect函数原理SSL(SecureSocketsLayer)是一种安全协议,用于在计算机网络上进行加密通信,保护数据传输的安全性和完整性。

在OpenSSL库中,ssl_connect函数用于启动SSL连接建立过程,该过程包括与服务器交换加密密钥和证书等安全措施。

本文将详细介绍ssl_connect函数的原理和实现方式。

ssl_connect函数是OpenSSL库中用于建立SSL连接的核心函数之一。

它负责与服务器进行通信,交换加密密钥和证书等安全信息,并建立安全的SSL连接。

该函数通常在客户端应用程序中使用,用于与服务器进行加密通信。

1.参数解析:ssl_connect函数接受一系列参数,包括要连接的服务器的地址和端口号、SSL协议版本、加密算法等信息。

这些参数用于初始化SSL连接。

2.连接建立:ssl_connect函数使用TCP/IP协议建立与服务器的连接,并使用SSL协议进行通信。

在连接建立过程中,客户端向服务器发送SSL握手消息,以便双方协商加密算法、密钥和证书等信息。

3.交换证书:在SSL握手过程中,客户端和服务器交换各自的证书,包括公钥和身份信息。

这些证书用于验证对方的身份,确保通信的安全性。

4.密钥协商:客户端和服务器协商生成一个共享的会话密钥,用于后续的数据加密和解密操作。

这个过程通常使用对称加密算法(如AES)进行加密和解密。

5.数据传输:一旦建立了SSL连接,客户端就可以使用该连接发送和接收加密的数据。

数据在传输过程中使用之前协商的会话密钥进行加密和解密,确保数据的安全性。

6.连接关闭:当客户端或服务器不再需要使用SSL连接时,可以使用ssl_close函数关闭连接。

ssl_connect函数的实现涉及多个步骤和算法,包括TCP/IP连接建立、SSL握手、证书交换、密钥协商等。

具体的实现方式取决于OpenSSL库的实现代码。

一般来说,ssl_connect函数会调用其他OpenSSL库中的函数来完成这些操作。

CISP考试认证(习题卷1)

CISP考试认证(习题卷1)

CISP考试认证(习题卷1)第1部分:单项选择题,共94题,每题只有一个正确答案,多选或少选均不得分。

1.[单选题]为了保障系统安全,某单位需要对其跨地区大型网络实时应用系统进行渗透测试, 以下关于渗透测试过程的说法不正确的是( )。

A)由于在实际渗透测试过程中存在不可预知的风险,所以测试前要提醒用户进行系统和数 据备份,以便出现问题时可以及时恢复系统和数据B)为了深入发掘该系统存在的安全威胁,应该在系统正常业务运行高峰期进行渗透测试C)渗透测试从“逆向”的角度出发,测试软件系统的安全性,其价值在于可以测试软件在实 际系统中运行时的安全状况D)渗透测试应当经过方案制定、信息收集、漏洞利用、完成渗透测试报告等步骤答案:B解析:在正常业务运行高峰期进行渗透测试可能会影响系统正常运行。

2.[单选题]我国信息安全标准化技术委员会(TC260)目前下属6 个工作组,其中负责信息安全管理的小组是:A)WG1B)WG7C)WG3D)WG5答案:B解析:3.[单选题]以下哪个现象较好的印证了信息安全特征中的动态性( )A)经过数十年的发展,互联网上已经接入了数亿台各种电子设备B)刚刚经过风险评估并针对风险采取处理措施后仅一周,新的系统漏洞使得信息系统面临新的风险C)某公司的信息系统面临了来自美国的“匿名者”黑客组织的攻击D)某公司尽管部署了防火墙、防病毒等安全产品,但服务器中数据仍然产生了泄露答案:B解析:B 体现出了动态性4.[单选题]鉴别是用户进入系统的第一道安全防线, 用户登录系统时。

输入用户名和密码就是对用户身份鉴别。

鉴别通过, 即可以实现两个实体之间的连接。

例如, 一个用户被服务器鉴别通过后, 则被服务器认为是合法用户,才可以进行后续访问。

鉴别是对是信息的一项安全属性进行验证, 该属性属于下列选项中的( )A)保密性B)可用性C)真实性D)完整性答案:C解析:5.[单选题]从业务角度出发,最大的风险可能发生在那个阶段A)立项可行性分析阶段B)系统需求分析阶段C)架构设计和编码阶段D)投产上线阶段答案:A解析:6.[单选题]460.一个信息管理系统通常会对用户进行分组并实施访问控制,例如,在一个学校的教务系统中,教师能够录入学生的考试成绩,学生只能查看自己的分数,而学校教务部门的管理人员能够对课程信息、学生的选课信息等内容进行修改,下列选项中,对访问控制的作用的理解错误的是()A)对经过身份鉴别后的合法用户提供所有服务B)拒绝非法用户的非授权访问请求C)在用户对系统资源提供最大限度共享的基础上,对用户的访问权进行管理D)防止对信息的非授权篡改和滥用答案:A解析:7.[单选题]30. 从 Linux 内核 2.1 版开始,实现了基于权能的特权管理机制,实现了超级用户的特权分割,打破了UNIX/LINUX 操作系统中超级用户/普通用户的概念,提高了操作系统的安全性。

linux openssl 连接 参数

linux openssl 连接 参数

linux openssl 连接参数在Linux中,OpenSSL是一个强大的工具,用于处理SSL和TLS协议,包括创建证书、生成密钥以及建立安全连接等。

当使用OpenSSL连接到远程服务器时,可以通过指定不同的参数来满足特定的需求。

首先,为了建立一个安全的连接,可以使用openssl s_client命令。

这个命令模拟了一个客户端,可以与远程服务器建立SSL/TLS连接,并返回与OpenSSL相关的信息。

其中,-connect参数用于指定要连接的远程服务器的地址和端口号。

例如,要连接到的443端口(默认端口),可以使用以下命令:bashopenssl s_client -connect:443这将启动一个SSL/TLS握手过程,并与服务器建立连接。

如果连接成功,将显示与服务器的证书相关的信息。

另外,当使用OpenSSL建立服务器时,可以使用openssl s_server命令。

这个命令模拟了一个服务器,可以监听指定的端口,并提供SSL/TLS服务。

其中,-accept参数用于指定监听的端口号,-cert和-key参数分别用于指定服务器的证书和私钥文件。

例如,要监听443端口并使用myserver.crt作为证书文件和myserver.key作为私钥文件,可以使用以下命令:bashopenssl s_server -accept 443 -cert myserver.crt -key myserver.key这将启动一个服务器,监听指定的端口,并等待客户端的连接请求。

此外,还可以使用其他参数来进一步定制OpenSSL的行为。

例如,参数可以在服务器上启用请求解析,以便处理HTTP请求。

另外,还可以使用-cert和-key参数将证书和私钥合并到一个文件中,以便在启动服务器时只提供一个参数。

总之,在Linux中使用OpenSSL连接时,可以通过指定不同的参数来满足特定的需求。

这些参数可以帮助你建立安全的连接、启动服务器以及定制OpenSSL的行为。

openssl使用流程

openssl使用流程

openssl使用流程OpenSSL使用流程介绍OpenSSL 是一个开源的加密工具包和安全通信协议实现库,提供了一系列的加密算法、SSL/TLS 防护和各种安全工具,广泛应用于网络通信、服务器配置、数字证书管理等各个领域。

本文将以OpenSSL 的使用流程为主题,一步一步详细回答。

一、准备工作1. 下载和安装OpenSSL:首先,我们需要从OpenSSL 的官方网站或其他可信来源下载并安装OpenSSL。

根据操作系统的不同,选择相应的版本进行下载和安装。

2. 生成RSA 密钥对:在开始使用OpenSSL 之前,建议先生成一对RSA 密钥对,用于后续的加密和解密操作。

在命令行中输入以下命令可以生成一个2048 位的RSA 密钥对:openssl genrsa -out private.key 2048该命令将生成一个名为private.key 的私钥文件,其中包含了生成的RSA 私钥。

接着,可以使用以下命令生成对应的公钥文件:openssl rsa -in private.key -pubout -out public.key这将生成一个名为public.key 的公钥文件,其中包含了与私钥对应的RSA 公钥。

二、公钥加密和私钥解密1. 加密数据:使用公钥加密数据是一种常见的操作,可以保证数据在传输过程中的机密性。

在命令行中输入以下命令可以使用公钥对数据进行加密:openssl rsautl -encrypt -pubin -inkey public.key -in plaintext.txt -out ciphertext.enc该命令将使用public.key 中的公钥对plaintext.txt 中的明文数据进行加密,并将密文数据存储到ciphertext.enc 文件中。

2. 解密数据:解密数据需要使用对应的私钥进行操作。

在命令行中输入以下命令可以使用私钥对密文数据进行解密:openssl rsautl -decrypt -inkey private.key -in ciphertext.enc -out plaintext.txt该命令将使用private.key 中的私钥对ciphertext.enc 中的密文数据进行解密,并将解密后的明文数据存储到plaintext.txt 文件中。

基于OpenSSL的安全密码平台的设计与实现

基于OpenSSL的安全密码平台的设计与实现
齐洪喜 , 周 大水
( 东大学 网络信 息安 全研 究 所 ,山 东 济 南 200) 山 5 10
摘 要 : 在对 O e S L开发 包进行研 究和分析 的基础 上 , 出 了一种基 于 O e S L的安 全 密码 平 台实现方案 。通过对 O e— pnS 提 pn S pn S L密码运 算功能 的抽 象及其 eg e S ni 机制 的研 究, 装 了易于上层安 全应 用调用 的接 口, n 封 保证 了网络 数据传输 的安全 性 , 使 该平 台不但具有 良好的应 用性和可 移植 性 , 而且具有对 各种硬 件 密码设 备 的 良好 的兼容性 。 关键词 : 密码 平 台;安全 套接 层; 引 擎; 公钥基础 设施 ; 网络 安全 中图法分 类号 :P 9.8 T 33 0 文献标识 码: A 文章编 号 :0072 20 ) 20 1。2 10—04(0 7 0 —340
Ab t a t Bya a y i gt eOp n S , as h meo s c r r p op a f r b s do i e . Ba e nt ea s a t no cy t p — sr c : n lz n e S L h c e f e u ecy t lto m a e ni i gv n ts s d o b t ci f r p oo e h r o
得 到 l ey 21 i a3 . b i b和 sl y 21 s a3 . e i 及 两 个 动 态链 接 sl y 2 I b以 s a3 .l e d
和 l e y 2dl i a 3 .l。 b
密 码 平 台来 实 现 各 个 实 体 数 字 信 息 的保 密 性 、 整 性 , 完 以及 相 互 的身 份 认 证 , 问控 制 以及 抗 抵 赖 服 务 。 pn S (pns— 访 ’ e S Lo e O e cr sce yr 一 个 优 秀 的开 放 源 代 码 的项 目, 仅 实 现 ue okt l e) sa 是 不 了 S L协议 , 且 拥 有 功 能 强 大 的 密 码 库 , S 而 能够 提 供 几 乎 所 有 的 P I 务 。本 文 先 O e S L作 了简 要 介 绍 , 后 给 出 了 一 K服 pnS 然 个 在 O eS L 的 基础 上 设 的简 易 而高 效 安 全密 码 平 台 的设 计 pn S 包 方案, 对其 实现 要 点 进行 了介绍 , 后 对 该平 台进 行 详 细分 析 。 最

ubuntu 中openssl用法

ubuntu 中openssl用法

文章标题:深入探讨Ubuntu中OpenSSL的用法在计算机科学领域中,OpenSSL是一个非常重要的工具,它提供了一系列的加密和解密功能,同时还包括了SSL和TLS协议的支持。

在Ubuntu系统中,OpenSSL作为一个开源软件被广泛应用,它可以帮助用户加强系统的安全性,保护敏感数据的传输。

本文将深入探讨Ubuntu中OpenSSL的用法,从基础概念到高级应用,帮助读者更全面地了解和应用这一重要工具。

一、基本概念1. OpenSSL的定义OpenSSL是一个强大的加密工具包,它提供了各种加密算法、密码算法以及SSL/TLS协议的实现。

在Ubuntu系统中,OpenSSL常常被用来对数据进行加密和解密,以确保数据的安全传输。

2. 安装和配置在Ubuntu系统中,OpenSSL通常已经预装,如果需要特定版本或者更新版本,可以通过apt命令进行安装和升级。

配置方面,可以通过修改opensslf文件进行一些定制化的设定。

二、常用命令1. 生成证书在Ubuntu中,使用OpenSSL生成自签名证书是一个常见操作。

通过openssl命令行工具,可以轻松生成证书请求(CSR)、私钥和自签名证书。

2. 加密和解密OpenSSL提供了丰富的加密和解密命令,可以用来对文件进行加密和解密操作。

使用openssl enc命令可以对文件进行对称加密,而使用openssl rsautl命令可以使用RSA算法进行非对称加密和解密。

三、SSL/TLS配置1. 生成CSR和私钥在配置SSL/TLS证书时,通常需要生成证书请求(CSR)和私钥。

OpenSSL提供了一系列命令来生成CSR和私钥,并可以根据需要进行定制化的配置。

2. 配置HTTPS在Ubuntu中,配置HTTPS服务器通常需要使用OpenSSL生成证书、将证书配置到Web服务器中,以及进行相关的安全性加固操作。

OpenSSL提供了完备的工具集来帮助用户完成这些操作。

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

Web服务器为了支持https访问,通常会使用第三方库openssl实现,而且为了高性能采用异步事件驱动模型,因此连接套接字被设为非阻塞类型,本文在nginx ssl模块的基础上,简化提取它的核心框架,使用面向对象的方式描述,从握手、读写和关闭3个方面进行了分析,由于这3个操作都是异步的,因此操作失败后要调用SSL_get_error来获取错误码,有如下4种情况● SSL_ERROR_WANT_READ:操作没完成,需要在下一次读事件中继续● SSL_ERROR_WANT_WRITE:操作没完成,需要在下一次写事件中继续● SSL_ERROR_ZERO_RETURN:连接正常关闭● 其它:连接出错示例代码使用了libevent实现IO事件驱动,connection表示普通连接类,假设已经处理好了http数据的逻辑,实现在成员函数handle_read和handle_write内,虚函数recv、send和close 分别调用系统的API recv、send和close;ssl_conn_t表示安全连接类,由于只是IO处理不同:收到数据后解密,发送数据前加密。

解密后的操作和connection是一样的,因此ssl_conn_t继承connection,重写了recv、send和close,其中close调用了shutdown。

异步握手当在SSL端口接受到连接时,首先要进行握手,握手成功后才能收发数据,如果握手失败而且返回前2种错误码,那么要在下一次操作中继续握手。

1void ssl_conn_t::empty_handler(short ev)2{3}45void ssl_conn_t::handshake_handler(short ev)6{7 handshake();8}910void ssl_conn_t::handshake()11{12int ret = do_handshake();1314switch(ret){15case OP_OK:16 read_handler_ = &connection::handle_read;17 write_handler_ = &connection::handle_write;18 handle_read(EV_READ);19break;2021 }22}2324int ssl_conn_t::do_handshake()25{26 ssl_clear_error();2728int ret = SSL_do_handshake(ssl_);29if(1==ret){3031return OP_OK;32 }3334int sslerr = SSL_get_error(ssl_,ret), err;35switch(sslerr){36case SSL_ERROR_WANT_READ:37read_handler_ = (io_handler)&ssl_conn_t::handshake_handler;38write_handler_ = (io_handler)&ssl_conn_t::empty_handler;39return OP_AGAIN;4041case SSL_ERROR_WANT_WRITE:42read_handler_ = (io_handler)&ssl_conn_t::empty_handler;43write_handler_ = (io_handler)&ssl_conn_t::handshake_handler;44return OP_AGAIN;4546 }47}其中do_handshake是核心函数,调用了SSL_do_handshake来实现握手,当SSL_do_hand shake失败时,如果返回SSL_ERROR_WANT_READ,就改变读函数指针为handshake_handl er,写函数指针为empty_handler;如果返回SSL_ERROR_WANT_WRITE,就改变读函数指针为empty_handler,写函数指针为handshake_handler。

handshake_handler实现在读写事件中继续处理握手,而empty_handler是个空函数,什么也不做。

异步读写对于读操作失败,如果返回SSL_ERROR_WANT_WRITE,那么说明要在下一次写事件中继续读数据,因此要改变写函数指针,使其读数据,当读成功后,要还原写函数针,并激发一次写事件;对于写操作失败,如果返回SSL_ERROR_WANT_READ,那么说明要在下一次读事件中继续写数据,因此要改变读函数指针,使其写数据,当写成功后,要还原读函数指针,并激发一次读事件。

如果不还原读或写函数指针,那么会发生写或读混乱;还原后,要激发一次读或写事件,这是为了延续IO事件的进行,防止读写饿死。

1ssize_t ssl_conn_t::recv(void *buf,size_t len)2{3 ssl_clear_error();45int ret = SSL_read(ssl_,buf,len);6if(ret>0){7if(old_write_handler_){8 write_handler_ = old_write_handler_;9 old_write_handler_ = NULL;10 active_event(false);11 }12return ret;13 }1415int sslerr = SSL_get_error(ssl_,ret), err;16switch(sslerr){17case SSL_ERROR_WANT_READ:18return OP_AGAIN;1920case SSL_ERROR_WANT_WRITE:21if(NULL==old_write_handler_){22old_write_handler_ = write_handler_;23write_handler_ = (io_handler)&ssl_conn_t::write_handler;24 }25return OP_AGAIN;2627 }28}2930void ssl_conn_t::write_handler(short ev)31{32 (this->*read_handler_)(EV_WRITE);33}3435ssize_t ssl_conn_t::send(const void *buf,size_t len)36{37 ssl_clear_error();3839int ret = SSL_write(ssl_,buf,len);40if(ret>0){41if(old_read_handler_){42 read_handler_ = old_read_handler_;43 old_read_handler_ = NULL;44 active_event(true);45 }46return ret;47 }4849int sslerr = SSL_get_error(ssl_,ret), err;50switch(sslerr){51case SSL_ERROR_WANT_WRITE:52return OP_AGAIN;5354case SSL_ERROR_WANT_READ:55if(NULL==old_read_handler_){56old_read_handler_ = read_handler_;57read_handler_ = (io_handler)&ssl_conn_t::read_handler;58 }59return OP_AGAIN;6061 }62}6364void ssl_conn_t::read_handler(short ev)65{66 (this->*write_handler_)(EV_READ);67}其中recv调用SSL_read,如果失败并且返回SSL_ERROR_WANT_WRITE,就保存老的写函数指针,改变写函数指针为write_handler,write_handler实现在写事件中继续读数据;sen d调用SSL_write,如果失败并且返回SSL_ERROR_WANT_READ,就保存老的读函数指针,改变读函数指针为read_handler,read_handler实现在读事件中继续写数据。

异步关闭当握手或读写因连接关闭或出错而失败时,就要关闭连接了,如果失败并且返回SSL_ERROR_ WANT_READ或SSL_ERROR_WANT_WRITE,那么要在下一次读或写事件中继续关闭。

在这里,为了收到对方发送的协议退出包而完全退出,等待30秒再关闭,如果超时就直接关闭。

1void ssl_conn_t::shutdown(bool is_timeout/*=false*/)2{3if (do_shutdown(is_timeout) != OP_AGAIN)4 delete this;5}67int ssl_conn_t::do_shutdown(bool is_timeout)8{9int ret,mode;1011if(is_timeout){12 mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN;13 SSL_set_quiet_shutdown(ssl_,1);14 }else{1516 }17 SSL_set_shutdown(ssl_,mode);1819 ssl_clear_error();2021 ret = SSL_shutdown(ssl_);22if(1==ret)23return OP_OK;2425int sslerr = SSL_get_error(ssl_,ret), err;26switch(sslerr){2728case SSL_ERROR_WANT_READ:29case SSL_ERROR_WANT_WRITE:30 read_handler_ = (io_handler)&ssl_conn_t::shutdown_handler;31write_handler_ = (io_handler)&ssl_conn_t::shutdown_handler;3233if(SSL_ERROR_WANT_READ==sslerr){34struct timeval tv;35 _sec = 30,_usec = 0;36 add_event(true,tv);37 }38return OP_AGAIN;3940 }41}4243void ssl_conn_t::shutdown_handler(short ev)44{45 shutdown(ev&EV_TIMEOUT);46}其中do_shutdown是核心函数,调用SSL_shutdown实现,如果失败并且返回SSL_ERROR_WANT_R EAD或SSL_ERROR_WANT_WRITE,就改变读写函数指针为shutdown_handler,shutdown_han dler实现在读写事件中继续关闭处理。

相关文档
最新文档