第19章 利用OpenSSL实现安全的Web Server程序
- 格式:ppt
- 大小:482.00 KB
- 文档页数:23
OpenSSL简单介绍本⽂对密码学中常⽤的底层库OpenSSL进⾏简单说明,包括基本介绍、简单使⽤等内容。
简单介绍是密码学中⼀个流⾏的底层密码库,也是SSL和TLS最常见的开源实现。
SSL全称为Secure Sockets Layer,安全套接层协议( 对⽹络连接进⾏加密处理 )。
TLS全称为Transport Layer Security,安全传输层协议(由记录协议和握⼿协议组成 )。
SSL协议由Netscape(⽹景)公司开发,因为应⽤⼴泛,到了1999年SSL已经成为互联⽹上的事实标准。
同年,IETF把SSL标准化后改名为TLS,它建⽴在SSL 3.0协议规范上,是SSL的后续版本。
TLS 和 SSL,两者差别极⼩,可以简单看做是同⼀个东西的两个不同阶段。
是由⼀些志愿者合作开发的开源⼯具库,其⽬标是开发⼀个强壮的、具有完备功能的商业级⼯具集,以实现SSL 和 TLS协议以及⼀个全功能的通⽤加密库。
OpenSSL主要以C语⾔实现,⽬前最新稳定版本为2018年9⽉11⽇发布的1.1.1版本。
OpenSSL的主要组成❏ openssl 多⽤途的命令⾏⼯具。
❏ libcrypto 常⽤加密算法库。
❏ libssl 实现了SSL及TLS的加密模块应⽤库。
⽀持许多不同的加密算法:其中包括但不限于单向散列函数的、、MD2、、、、RIPEMD-160、MDC-2、GOST R 34.11-94、BLAKE2、Whirlpool、SM3等算法,对称加密有、Blowfish、Camellia、Chacha20、Poly1305、SEED、CAST-128、、IDEA、RC2、RC4、、SM4、TDES、GOST 28147-89等算法,以及⾮对称加密的、DSA、迪菲-赫尔曼密钥交换、椭圆曲线、SM2、X25519、Ed25519、X448、Ed448、GOST R 34.10-2001等算法。
参考资料opsnssl 命令⾏简单说明的安装通常,很多操作系统都会默认安装OpenSSL ⼯具,我们可以通过在终端中输⼊openssl version命令来查看和进⾏验证。
第11卷第1期沙洲职业工学院学报V ol. 11, No.1 2008年3月 Journal of Shazhou Professional Institute of Technology Mar. , 2008 利用OpenSSL实现IIS服务器安全通信汤建龙,陆国浩(沙洲职业工学院,江苏张家港 215600)摘要:简述了基于SSL的信息安全通道的原理及应用,介绍了利用OpenSSL软件包在windows 2000 server上IIS服务器搭建一条基于SSL的信息安全通道的过程,其中包括对CA服务的配置,WEB服务器端证书的申请、安装和配置,以及客户端和服务端SSL的通信过程。
关键词:OpenSSL;IIS;证书中图分类号:TP39 文献标识码:A 文章编号:1009-8429(2008)01-0012-05Realizing the Secure Communication on the IIS server with the OpenSSLTANG Jian-long,LU Guo-hao( Shazhou Professional Institute of Technology, Zhangjiagang 215600, China )Abstract: This paper summarizes the principle and the application of SSL-based information security channel, introduces the process for the SSL-based information security channel with the Open SSL software package on the Windows 2000 server and the IIS server, including the CA service configuration, the application for, the installation as well as the disposition of the WEB server certificate, and the SSL course of communications between the client end and the server end.Key words: OpenSSL; IIS; Certificate0 引言随着计算机网络技术的发展,互连网成为人们日常生活中获取信息的主要方式之一。
OpenSSL命令---s_client/as3luyuan123/article/details/16812071⽤途:s_client为⼀个SSL/TLS客户端程序,与s_server对应,它不仅能与s_server进⾏通信,也能与任何使⽤ssl协议的其他服务程序进⾏通信。
⽤法:[cpp]1. openssl s_client [-host host] [-port port] [-connect host:port] [-verify depth] [-cert filename]2. [-certform DER|PEM] [-key filename] [-keyform DER|PEM] [-pass arg] [-CApath directory] [-CAfile filename]3. [-reconnect][-pause] [-showcerts] [-debug] [-msg] [-state] [-nbio_test] [-nbio][-crlf] [-ign_eof] [-no_ign_eof]4. [-quiet] [-ssl2] [-ssl3] [-tls1_1] [-tls1_2] [-tls1] [-dtls1] [-no_ssl2][-no_ssl3] [-no_tls1] [-no_tls1_1]5. [-no_tls1_2] [-bugs] [-cipher cipherlist] [-starttls protocol] [-engine id] [-tlsextdebug] [-no_ticket]6. [-sess_out filename] [-sess_in filename] [-rand file(s)]选项说明:-host host:设置服务地址。
-port port:设置服务端⼝,默认为4433。
-connect host:port:设置服务器地址和端⼝号。
利⽤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);}。
openssl做证书的方法-回复OpenSSL 是一个开源的软件包,可用于创建安全套接字层(SSL)和传输层安全性(TLS)协议的证书。
证书是用于身份验证和数据加密的数字文件。
下面将一步一步介绍OpenSSL 的使用方法来生成证书。
第一步:安装OpenSSL首先,您需要安装OpenSSL 软件包。
根据您的操作系统,可以在OpenSSL 官方网站(OpenSSL 在您的系统上可用。
第二步:生成私钥要生成证书,首先需要生成一个私钥。
私钥用于生成和验证证书,因此它必须严格保密。
您可以使用以下命令在命令行中生成私钥:openssl genpkey -algorithm RSA -out private.key此命令将使用RSA 算法生成一个私钥,并将其保存在private.key 文件中。
确保将文件保存在安全的位置,并为其设置适当的权限,以防止未经授权访问。
第三步:生成证书请求生成了私钥后,接下来需要生成证书请求。
证书请求包含您的公钥以及有关您身份的信息。
以下命令将生成证书请求:openssl req -new -key private.key -out certificate.csr在此命令中,-key 参数指定您的私钥文件,-out 参数指定将保存证书请求的文件名。
您将被要求输入与您身份相关的信息,如名称、单位、电子邮件地址等。
确保在输入这些信息时提供准确的数据。
第四步:自签名证书生成证书请求后,您可以使用OpenSSL 生成一个自签名证书。
自签名证书是由您自己颁发的,因此在一些特定情况下可能不被所有设备或应用程序接受。
但它在测试和开发环境中非常有用。
以下命令将生成自签名证书:openssl x509 -req -in certificate.csr -signkey private.key -out certificate.crt此命令使用您之前生成的私钥和证书请求来创建一个自签名证书。
最后的证书将保存在certificate.crt 文件中。
openssl3 手册摘要:1.OpenSSL3 简介2.OpenSSL3 的安装与配置3.OpenSSL3 的功能与应用4.OpenSSL3 的安全性5.OpenSSL3 的未来发展正文:【OpenSSL3 简介】OpenSSL3 是一个强大的安全套接字层(SSL)库,用于加密网络通信。
它是OpenSSL2 的升级版本,提供了许多改进和新功能。
OpenSSL3 提供了广泛的加密和签名算法,支持各种安全协议,如TLS、SSL、DTLS 等。
它广泛应用于Web 服务器、客户端应用程序和各种网络设备中,保障网络通信的安全性。
【OpenSSL3 的安装与配置】安装OpenSSL3 非常简单,只需从官方网站下载源代码并按照官方文档进行编译和安装即可。
安装完成后,需要对OpenSSL3 进行配置,包括设置加密算法、证书、密钥等。
配置过程可以通过命令行工具或编译时选项完成。
【OpenSSL3 的功能与应用】OpenSSL3 提供了许多功能,包括加密、签名、哈希等。
它可以用于保护网络通信、数字签名文件、加密文件等。
OpenSSL3 还支持各种安全协议,如TLS、SSL、DTLS 等,可以满足各种应用场景的需求。
【OpenSSL3 的安全性】OpenSSL3 非常注重安全性,采用了多种措施来保障通信的安全性。
它支持多种加密算法,如AES、RSA、ECC 等,可以根据需求选择合适的加密算法。
此外,OpenSSL3 还支持证书验证、密钥交换、哈希函数等,可以有效防止各种攻击。
【OpenSSL3 的未来发展】随着网络通信的不断发展,OpenSSL3 将继续完善和升级,以适应新的需求。
未来,OpenSSL3 可能会引入更多的加密算法、支持更多的安全协议,并继续提高安全性能。
同时,OpenSSL3 还将加强与其他安全技术的集成,如IPsec、TLS 等,以提供更全面的安全解决方案。
总之,OpenSSL3 是一个重要的安全库,用于加密网络通信。
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使用指南0.7p目录1.介绍intro2.编译build3.运行OpenSSL.exe openssl_exe4.算法编程API Alg_API4.1 对称算法4.1.1 DES4.1.2 AES4.1.3 RC44.1.4 EVP_4.2 公钥算法4.3 Hash算法4.4 随机数算法5.SSL协议编程API SSL6.CA和证书CA7.参考网址REF8.A.示例程序demoB.其他C.其他示例程序D.1.介绍OpenSSL是使用非常广泛的SSL的开源实现。
由于其中实现了为SSL所用的各种加密算法,因此OpenSSL也是被广泛使用的加密函数库。
1.1 SSLSSL(Secure Socket Layer)安全协议是由Netscape公司首先提出,最初用在保护Navigator浏览器和Web服务器之间的HTTP通信(即HTTPS)。
后来SSL协议成为传输层安全通信事实上的标准,并被IETF吸收改进为TLS(Transport Layer Security)协议。
SSL/TLS协议位于TCP协议和应用层协议之间,为传输双方提供认证、加密和完整性保护等安全服务。
SSL作为一个协议框架,通信双方可以选用合适的对称算法、公钥算法、MAC 算法等密码算法实现安全服务。
1.2 SSL的工作原理参见/tech/security/ssl/howitworks.html。
1.3 OpenSSLOpenSSL是著名的SSL的开源实现,是用C语言实现的。
OpenSSL的前身是SSLeay,一个由Eric Young开发的SSL的开源实现,支持SSLv2/v3和TLSv1。
伴随着SSL协议的普及应用,OpenSSL被广泛应用在基于TCP/Socket的网络程序中,尤其是OpenSSL和Apache相结合,是很多电子商务网站服务器的典型配置。
2.编译和安装OpenSSLOpenSSL开放源代码,这对学习、分析SSL和各种密码算法提供了机会,也便于在上面进一步开发。
使用OpenSSL API 进行安全编程创建基本的安全连接和非安全连接Kenneth Ballard (kenneth.ballard@), 自由程序员简介:学习如何使用 OpenSSL ——用于安全通信的最著名的开放库——的API 有些强人所难,因为其文档并不完全。
您可以通过本文中的提示补充这方面的知识,并驾驭该 API。
在建立基本的连接之后,就可以查看如何使用 OpenSSL 的 BIO 库来建立安全连接和非安全连接。
与此同时,您还会学到一些关于错误检测的知识。
OpenSSL API 的文档有些含糊不清。
因为还没有多少关于 OpenSSL 使用的教程,所以对初学者来说,在应用程序中使用它可能会有一些困难。
那么怎样才能使用 OpenSSL 实现一个基本的安全连接呢?本教程将帮助您解决这个问题。
学习如何实现 OpenSSL 的困难部分在于其文档的不完全。
不完全的 API 文档通常会妨碍开发人员使用该 API,而这通常意味着它注定要失败。
但 OpenSSL 仍然很活跃,而且正逐渐变得强大。
这是为什么?OpenSSL 是用于安全通信的最著名的开放库。
在 google 中搜索“SSL library”得到的返回结果中,列表最上方就是 OpenSSL。
它诞生于 1998 年,源自 Eric Young 和 Tim Hudson 开发的 SSLeay 库。
其他 SSL 工具包包括遵循 GNU General Public License 发行的 GNU TLS,以及 Mozilla Network Security Services(NSS)(请参阅本文后面的参考资料,以获得其他信息)。
那么,是什么使得 OpenSSL 比 GNU TLS、Mozilla NSS 或其他所有的库都优越呢?许可是一方面因素(请参阅参考资料)。
此外,GNS TLS(迄今为止)只支持 TLS v1.0 和 SSL v3.0 协议,仅此而已。
openssl生成的各种证书用法-概述说明以及解释1.引言1.1 概述在当今数字化信息时代,网络安全问题备受关注。
而证书作为一种数字证明方式,扮演着保障网络通信安全的重要角色。
OpenSSL是一个强大的加密工具包,可以用来生成各种类型的证书,包括服务器证书、客户端证书、中间CA证书等。
本文将介绍OpenSSL生成证书的基本概念,不同类型证书的用途和生成方法,以及证书的应用场景和注意事项。
通过全面了解OpenSSL证书生成的流程和用法,读者可以更好地保障自己的网络通信安全,防范各种网络攻击。
1.2 文章结构本篇文章将围绕openssl生成的各种证书的用法展开讨论。
主要分为引言、正文和结论三个部分。
引言部分将介绍文章的背景和概要,提出文章的目的和重要性。
通过引言部分,读者将对文章内容有一个初步了解。
正文部分将介绍openssl生成证书的基本概念,包括证书的定义、结构和工作原理。
然后详细探讨不同类型证书的用途和生成方法,例如SSL 证书、数字证书、代码签名证书等,以及如何使用openssl生成这些证书。
在证书的应用场景和注意事项部分,我们将讨论证书在网络安全中的重要性,以及需要注意的安全问题和最佳实践。
读者将了解到如何正确地使用和管理证书,以保障网络安全。
在结论部分,我们将总结openssl生成证书的重要性,强调证书在网络安全中的作用,并展望未来openssl证书生成的发展趋势。
读者将对openssl证书生成技术有一个全面的认识,为提升网络安全水平提供参考和指导。
1.3 目的在本文中,我们的目的是深入探讨openssl生成各种证书的方法和用途。
通过了解openssl生成证书的基本概念、不同类型证书的用途和生成方法,以及证书在网络安全中的重要性和应用场景,我们可以更好地理解如何使用openssl生成和管理证书来保障网络通信的安全性。
同时,我们还将探讨未来openssl证书生成的发展趋势,帮助读者更好地把握证书技术的发展方向,从而更好地保护网络安全。
OpenSSL程序编写步骤OpenSSL是一个开放源代码的SSL协议的产品实现,它采用C语言作为开发语言,具备了跨系统的性能。
调用OpenSSL 的函数就可以实现一个SSL加密的安全数据传输通道,从而保护客户端和服务器之间数据的安全。
头文件:#include <openssl/ssl.h>#include <openssl/err.h>基于OpenSSL的程序都要遵循以下几个步骤:(1 ) OpenSSL初始化在使用OpenSSL之前,必须进行相应的协议初始化工作,这可以通过下面的函数实现:int SSL_library_int(void);(2 ) 选择会话协议在利用OpenSSL开始SSL会话之前,需要为客户端和服务器制定本次会话采用的协议,目前能够使用的协议包括TLSv1.0、SSLv2、SSLv3、SSLv2/v3。
需要注意的是,客户端和服务器必须使用相互兼容的协议,否则SSL会话将无法正常进行。
(3 ) 创建会话环境在OpenSSL中创建的SSL会话环境称为CTX,使用不同的协议会话,其环境也不一样的。
申请SSL会话环境的OpenSSL函数是:SSL_CTX *SSL_CTX_new(SSL_METHOD * method);当SSL会话环境申请成功后,还要根据实际的需要设置CTX的属性,通常的设置是指定SSL 握手阶段证书的验证方式和加载自己的证书。
制定证书验证方式的函数是:int SSL_CTX_set_verify(SSL_CTX *ctx,int mode,int(*verify_callback),int(X509_STORE_CTX *));为SSL会话环境加载CA证书的函数是:SSL_CTX_load_verify_location(SSL_CTX *ctx,const char *Cafile,const char *Capath);为SSL会话加载用户证书的函数是:SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file,int type);为SSL会话加载用户私钥的函数是:SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx,const char* file,int type);在将证书和私钥加载到SSL会话环境之后,就可以调用下面的函数来验证私钥和证书是否相符:int SSL_CTX_check_private_key(SSL_CTX *ctx);(4) 建立SSL套接字SSL套接字是建立在普通的TCP套接字基础之上,在建立SSL套接字时可以使用下面的一些函数:SSL *SSl_new(SSL_CTX *ctx);//申请一个SSL套接字int SSL_set_fd(SSL *ssl,int fd);)//绑定读写套接字int SSL_set_rfd(SSL *ssl,int fd);//绑定只读套接字int SSL_set_wfd(SSL *ssl,int fd);//绑定只写套接字(5) 完成SSL握手在成功创建SSL套接字后,客户端应使用函数SSL_connect( )替代传统的函数connect( )来完成握手过程:int SSL_connect(SSL *ssl);而对服务器来讲,则应使用函数SSL_ accept ( )替代传统的函数accept ( )来完成握手过程:int SSL_accept(SSL *ssl);握手过程完成之后,通常需要询问通信双方的证书信息,以便进行相应的验证,这可以借助于下面的函数来实现:X509 *SSL_get_peer_certificate(SSL *ssl);该函数可以从SSL套接字中提取对方的证书信息,这些信息已经被SSL验证过了。
目录一、实验选题 (2)二、实验环境 (2)三、系统设计 (2)1、Windows下进行OpenSSL编程的主要步骤 (2)2、系统框图 (3)3、重要函数 (3)四、实验过程截图 (15)1、安装openssl (16)2、客户端与服务器端安全通信 (17)五、实验与课程总结 (19)六、源代码清单 (19)一、实验选题基于OpenSSL的安全聊天系统–Windows或Linux平台均可–点到点模式–基于OpenSSL的安全套接字通信–客户端服务器双向认证–聊天记录本地加密存储,输入正确口令可查看二、实验环境操作系统Windows XP sp3开发平台VC++6.0其它OpenSSL ActivePerl三、系统设计1、Windows下进行OpenSSL编程的主要步骤1.安装ActivePerl,阅读openssl开发包中的install.w32 ,编译openssl,;2.下载CA证书并对其进行公私钥的分割,使用openssl生成证书文件;3.阅读相关文档,熟悉OpenSSL编程接口,编写server和client端代码;4.将所需要的文件放到源代码目录,调试并运行程序,使用证书来验证进行安全通信的过程及身份认证方式。
2、系统框图3、重要函数Client :连接服务器端并接收服务器消息的线程函数:void ClientThreadProc(void* void_parm){WSADATA wsaData;int err;int sd;struct sockaddr_in sa;SSL* ssl;X509* server_cert;char* str; charbuffer [8912];int maxFd;fd_set writeFds, readFds, excFds;DWORD dwIP;dwIP = (DWORD)void_parm;//char *msg = (char *)malloc(128);char msg[128];//初始化windows socketif (WSAStartup(MAKEWORD(2, 2), &wsaData)){return;}//新建socketsd = socket (AF_INET, SOCK_STREAM, 0);memset (&sa, '\0', sizeof(sa));//设置服务端IP地址、和端口sa.sin_family = AF_INET;sa.sin_addr.s_addr = dwIP;sa.sin_port = htons(8443);//连接服务器err = connect(sd, (struct sockaddr*) &sa,sizeof(sa));if(err < 0){// char *msg = (char *)malloc(128);strcpy(msg,"连接服务器失败!");SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_STATE_MSG,sd,(long )msg);return;}strcpy(msg,"SSL开始握手!");SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_STATE_MSG,sd,(long )msg);//新建SSL句柄ssl = SSL_new (ctx);//设置socket句柄到SSL句柄SSL_set_fd (ssl, sd);//SSL连接err = SSL_connect (ssl);if(err != 1){// char *msg = (char *)malloc(128);strcpy(msg,"SSL连接服务器失败!");SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_STATE_MSG,sd,(long )msg);return;}server_cert = SSL_get_peer_certificate (ssl);strcpy(msg,"Client certificate:");SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_STATE_MSG,sd,(long )msg);str = X509_NAME_oneline (X509_get_subject_name (server_cert),0,0);strcpy(msg,"subject: ");SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_STATE_MSG,sd,(long )msg);strcpy(msg,str);SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_STATE_MSG,sd,(long )msg);OPENSSL_free (str);str = X509_NAME_oneline (X509_get_issuer_name (server_cert),0,0);strcpy(msg,"issuer:");SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_STATE_MSG,sd,(long )msg);strcpy(msg,str);SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_STATE_MSG,sd,(long )msg);OPENSSL_free (str);X509_free (server_cert);// printf ("SSL connection using %s\n", SSL_get_cipher (ssl));strcpy(msg,"SSL connection using:");SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_STATE_MSG,sd,(long )msg);/*打印所有加密算法的信息(可选)*/strcpy(msg,SSL_get_cipher (ssl));SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_STATE_MSG,sd,(long )msg);maxFd = sd;client.fd=sd;client.ssl=ssl;strcpy(msg,"连接服务器成功!");SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_STATE_MSG,sd,(long )msg); for(;;){FD_ZERO(&writeFds);FD_ZERO(&readFds);FD_ZERO(&excFds);FD_SET(sd, &readFds);//select 异步等待服务器int nfd = select(maxFd + 1, &readFds, &writeFds, &excFds, NULL);if(nfd <= 0){if(errno == EINTR) /* interrupted system call */continue;return;}if(FD_ISSET(sd, &readFds)){//接收服务器消息int len = SSL_read(ssl,buffer,sizeof(buffer));if(len <=0){char *msg = (char *)malloc(128);strcpy(msg,"服务器退出!");SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_STATE_MSG,sd,(long )msg);return;}buffer[len]='\0';char *msg = (char *)malloc(len +1);strcpy(msg,buffer);//通过WM_CLIENT_MSG消息,发送到主窗体SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_CLIENT_MSG,sd,(long )msg);}}return;}链接服务器:void CClientDlg::OnConnect(){unsigned long idThread;DWORD dwIP=0;CIP ipaddr;//让用户输入客户端IPm_liststate.ResetContent();if(client.fd==0)//判断是否已经连接{if(ipaddr.DoModal() == IDOK){dwIP=inet_addr(ipaddr.IP.GetBuffer(0));}//创建线程,连接服务器,并接收服务器端消息CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ClientThreadProc,(void *)dwIP, 0 ,&idThread);}else{m_liststate.InsertString(0,"已经连接!");}}发送消息到服务器:void CClientDlg::OnSend(){UpdateData();if(client.fd !=0){//发送消息SSL_write(client.ssl,m_str.GetBuffer(0),m_str.GetLength());m_str.ReleaseBuffer();}else{return;}//插入发送的消息的列表框m_list.InsertString(0,m_str);m_str.Empty();UpdateData(FALSE);((CEdit *)GetDlgItem(IDC_EDIT1))->SetActiveWindow();}处理WM_CLIENT_MSG消息:LRESULT CClientDlg::OnClientMsg(WPARAM wParam,LPARAM lParam) {CString msg;msg.Format("[Socket:%d]%s",wParam,(char *)lParam);m_list.InsertString(0,msg);free((void*)lParam);return 0L;}LRESULT CClientDlg::OnStateMsg(WPARAM wParam,LPARAM lParam) {CString msg;msg.Format("[Socket:%d]%s",wParam,(char *)lParam);m_liststate.InsertString(-1,msg);// m_liststate.AddString(msg);// free((void*)lParam);return 0L;}void CClientDlg::OnDestroy(){WSACleanup();SSL_CTX_free(ctx);CDialog::OnDestroy();}断开链接:void CClientDlg::OnDisconnect(){if(client.fd !=0){closesocket(client.fd);SSL_shutdown(client.ssl);SSL_free(client.ssl);client.ssl=NULL;client.fd=0;m_liststate.InsertString(0,"已断开和服务器的链接!");m_liststate.ResetContent();}}Server:处理客户端事务线程函数,接收客户端消息:void client( void* void_parmint ){int clientFd = (int) void_parmint;int maxFd;int len;int flag=0;fd_set writeFds, readFds, excFds;char buffer[8192];descriptor_t clientDesc;clientDesc.fd = clientFd;clientDesc.ssl = NULL;SSL *ssl;char *str;X509* client_cert;//新建SSL连接句柄if((ssl = SSL_new(ctx)) == NULL){return;}//设置SSL连接Socket句柄SSL_set_fd(ssl, clientFd);//接收SSL连接if(SSL_accept(ssl) <= 0){return;}// char *msg = (char *)malloc(128);char msg[128];strcpy(msg,"SSL connection using");SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_STATE_MSG,clientFd,(long )msg );/*打印所有加密算法的信息(可选)*/strcpy(msg,SSL_get_cipher (ssl));SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_STATE_MSG,clientFd,(long )msg );/*得到客户端的证书并打印些信息(可选) */client_cert = SSL_get_peer_certificate (ssl);if (client_cert != NULL) {// printf ("Client certificate:\n");strcpy(msg,"Client certificate:");SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_STATE_MSG,clientFd,(long )msg );str=X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0);//printf ("\t subject: %s\n", str);strcpy(msg,"subject:");SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_STATE_MSG,clientFd,(long )msg );SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_STATE_MSG,clientFd,(long )str);OPENSSL_free (str);str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0);//printf ("\t issuer: %s\n", str);strcpy(msg,"issuer:");SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_STATE_MSG,clientFd,(long )msg );SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_STATE_MSG,clientFd,(long )str);OPENSSL_free (str);X509_free (client_cert);/*如不再需要,需将证书释放*/}clientDesc.ssl = ssl;//把客户端链接句柄保存到全局变量中。
Openssl安装及使用一软件Windows下需要用到的软件•C++编译器编译器就是将“高级语言”翻译为“机器语言(低级语言)”的程序。
一个现代编译器的主要工作流程:源代码(source code) → 预处理器(preprocessor) → 编译器(compiler) → 汇编程序(assembler) → 目标代码(object code) → 链接器(Linker) → 可执行程序(executables)。
c++编译器是一个与标准化C++高度兼容的编译环境。
这点对于编译可移植的代码十分重要。
编译器对不同的CPU会进行不同的优化。
•ActivePerl一个perl脚本解释器。
其包含了包括有Perl for Win32、Perl for ISAPI、PerlScript、Perl Package Manager四套开发工具程序,可以让你编写出适用于unix,windows,linux系统的CGI程序来。
安装的只是perl的一个解释程序啦,外观上也不会发生什么变化,你在windows的cmd界面里输入perl -v可查看你所安装的版本。
在你编译perl程序时会用到它。
法、常用的密钥和证书封装管理功能以及SSL协议,并提供了丰富的应用程序供测试或其它目的使用。
•MASM 8.0•MASM是微软公司开发的汇编开发环境,拥有可视化的开发界面,使开发人员不必再使用DOS环境进行汇编的开发,编译速度快,支持80x86汇编以及Win32Asm是Windows下开发汇编的利器。
它与windows平台的磨合程度非常好,但是在其他平台上就有所限制,使OpenSSLOpenSSL是一个强大的安全套接字层密码库,Apache使用它加密HTTPS,OpenSSH使用它加密SSH,它还是一个多用途的、跨平台的密码工具。
OpenSSL整个软件包大概可以分成三个主要的功能部分:密码算法库、SSL协议库以及应用程序。
OpenSSL的目录结构自然也是围绕这三个功能部分进行规划的。
Openssl实现双向认证教程(附服务端客户端代码)⼀、背景说明1.1 ⾯临问题最近⼀份产品检测报告建议使⽤基于pki的认证⽅式,由于产品已实现https,商量之下认为其意思是使⽤双向认证以处理中间⼈形式攻击。
《信息安全⼯程》中接触过双向认证,但有两个问题。
第⼀个是当时最终的课程设计客户端是浏览器,服务端是tomcat双向认证只需要对两者进⾏配置并不需要⾃⼰真的实现代码。
第⼆个是虽然课程也有接近双向认证的实现代码,但当时是Java+JCE环境现在要⽤C+++OpenSSL环境,总体意思确实还是差不多但具体函数和参数差别还是不少。
所以眼下有的是:证书⽣成的思想+双向认证实现的思想。
对读者⽽⾔,即要假定已对证书、SSL/TSL、socket编程等⼏个概念有基本的了解,本⽂不做详细介绍。
基于此本⽂要解决的问题是:openssl具体如何⽣成证书+openssl如何实现双向认证。
双向认证的关键点在以下⼏个函数(服务端和客户端都⼀样),其他就不细说参看代码注释:SSL_CTX_set_verify----配置启⽤双向认证SSL_CTX_load_verify_locations----加载信任的根证书SSL_CTX_use_certificate_file----加载⾃⼰的证书SSL_CTX_use_PrivateKey_file----加载⾃⼰的私钥SSL_get_verify_result----真正进⾏验证,⼀定要调⽤这个函数不然前⾯四个光配置⽽已并不会进⾏双向验证⼆、双向认证程序实现2.1 安装openssl及开发apiapt-get install libssl-dev2.2 服务端代码#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <sys/types.h>#include <netinet/in.h>#include <sys/socket.h>#include <sys/wait.h>#include <unistd.h>#include <arpa/inet.h>#include <openssl/ssl.h>#include <openssl/err.h>#define MAXBUF 1024void ShowCerts(SSL * ssl){X509 *cert;char *line;cert = SSL_get_peer_certificate(ssl);// SSL_get_verify_result()是重点,SSL_CTX_set_verify()只是配置启不启⽤并没有执⾏认证,调⽤该函数才会真证进⾏证书认证// 如果验证不通过,那么程序抛出异常中⽌连接if(SSL_get_verify_result(ssl) == X509_V_OK){printf("证书验证通过\n");}if (cert != NULL) {printf("数字证书信息:\n");line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);printf("证书: %s\n", line);free(line);line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);printf("颁发者: %s\n", line);free(line);X509_free(cert);} elseprintf("⽆证书信息!\n");}int main(int argc, char **argv) {int sockfd, new_fd;socklen_t len;struct sockaddr_in my_addr, their_addr;unsigned int myport, lisnum;char buf[MAXBUF + 1];SSL_CTX *ctx;if (argv[1])myport = atoi(argv[1]);elsemyport = 7838;if (argv[2])lisnum = atoi(argv[2]);elselisnum = 2;/* SSL 库初始化 */SSL_library_init();/* 载⼊所有 SSL 算法 */OpenSSL_add_all_algorithms();/* 载⼊所有 SSL 错误消息 */SSL_load_error_strings();/* 以 SSL V2 和 V3 标准兼容⽅式产⽣⼀个 SSL_CTX ,即 SSL Content Text */ctx = SSL_CTX_new(SSLv23_server_method());/* 也可以⽤ SSLv2_server_method() 或 SSLv3_server_method() 单独表⽰ V2 或 V3标准 */if (ctx == NULL) {ERR_print_errors_fp(stdout);exit(1);}// 双向验证// SSL_VERIFY_PEER---要求对证书进⾏认证,没有证书也会放⾏// SSL_VERIFY_FAIL_IF_NO_PEER_CERT---要求客户端需要提供证书,但验证发现单独使⽤没有证书也会放⾏ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);// 设置信任根证书if (SSL_CTX_load_verify_locations(ctx, "ca.crt",NULL)<=0){ERR_print_errors_fp(stdout);exit(1);}/* 载⼊⽤户的数字证书,此证书⽤来发送给客户端。