OpenSSL编程实例
Linux系统利用OpenSSL生成SSL证书
Linux上使用OpenSSL生成SSL证书Linux上使用OpenSSL生成SSL证书1 安装OpenSSL2 生成私钥文件(KEY)3 生成证书请求文件(CSR)4 生成自签名证书(CRT)5 配置服务器1 安装OpenSSL在终端输入以下命令来检查是否已安装OpenSSL:openssl version如果已安装,则可以看到OpenSSL的版本号。
如果未安装,需要根据所使用的Linux发行版进行安装,例如:Debian/Ubuntu:sudo apt-get install opensslCentOS/RHEL:sudo yum install openssl2 生成私钥文件(KEY)1. 执行以下命令生成一个私钥文件(例如private.key):openssl genrsa -out private.key 2048以上示例将生成一个2048位的RSA私钥。
3 生成证书请求文件(CSR)1. 执行以下命令生成一个证书请求文件(例如server.csr):openssl req -new-key private.key -out server.csr2. 在生成CSR的过程中,需要提供一些证书信息,例如:常用名称、国家、email、组织名称等,详细信息如下:You are about to be asked to enter information that will be incorporatedinto your certificate request.What you are about to enter is what is called a Distinguished Name or a DN.There are quite a few fields but you can leave some blankFor some fields there will be a default value,If you enter '.', the field will be left blank.-----Country Name (2 letter code) [XX]:cnState or Province Name (full name) []:bjLocality Name (eg, city) [Default City]:bjOrganization Name (eg, company) [Default Company Ltd]:bjOrganizational Unit Name (eg, section) []:bj4 生成自签名证书(CRT )1.以上示例将生成一个有效期为365天的自签名证书,将使用私钥文件来签名证书请求文件,可以根据需要调整证书的有效期5 配置服务器将生成的私钥文件和证书文件配置到Nginx 或Apache 等服务器上即可使用。
openssl rsa 用法
OpenSSL RSA 用法简介OpenSSL 是一个强大且广泛使用的开源加密工具包,提供了一系列密码学功能,包括对 RSA 加密算法的支持。
RSA 是一种非对称加密算法,可以用于生成和管理公钥和私钥对,以及进行加密和解密操作。
本文将详细介绍 OpenSSL 中 RSA 的用法,包括生成 RSA 密钥对、加密和解密数据、签名和验证等操作。
安装 OpenSSL在开始使用 OpenSSL RSA 命令之前,需先安装 OpenSSL 工具包。
具体安装步骤如下:1.在 Linux 系统上,可以通过包管理器直接安装 OpenSSL。
例如,在 Ubuntu上可以使用以下命令进行安装:sudo apt-get install openssl2.在 Windows 系统上,可以从 OpenSSL 官方网站()下载预编译的二进制文件,并按照提示进行安装。
生成 RSA 密钥对要使用 RSA 加密算法,首先需要生成 RSA 密钥对。
RSA 密钥由一个公钥和一个私钥组成,其中公钥可用于加密数据,私钥可用于解密数据。
以下是使用 OpenSSL 生成 RSA 密钥对的步骤:1.打开终端或命令提示符,并执行以下命令:openssl genrsa -out private.pem 2048上述命令将生成一个 2048 位的 RSA 私钥,并保存到名为private.pem的文件中。
2.接下来,可以通过以下命令从私钥中导出公钥:openssl rsa -in private.pem -pubout -out public.pem上述命令将从private.pem文件中读取私钥,并将对应的公钥导出到名为public.pem的文件中。
现在,你已经成功生成了一个 RSA 密钥对,私钥保存在private.pem文件中,公钥保存在public.pem文件中。
加密和解密数据使用 OpenSSL RSA 加密和解密数据非常简单。
以下是使用 OpenSSL 进行 RSA 加密和解密的步骤:1.首先,创建一个文本文件(例如plaintext.txt),并输入要加密的数据。
OpenSSL之X509系列
OpenSSL之X509系列之1---引言和X509概述【引言】X509是系列的函数在我们开发与PKI相关的应用的时候我们都会用到,但是OpenSSL中对X509的描述并不是很多,鉴于些,我将以前工作与学习过程的经验整理出来,供大家参考,不用多走弯路,可以将精力集中在自己要处理的业务逻辑上,同时也希望更多的人参与到研究与整理信息安全的理论与技术中来,提高中国的科研与应用技术水平。
提高中国信息安全意识与能力从我做起。
【X509概述】X.509是国际标准化组织CCITT建议作为X.500目录检索的一部分提供安全目录检索服务。
一份X.509证书是一些标准字段的集合,这些字段包含有关用户或设备及其相应公钥的信息一种非常通用的证书格式,所有的证书都符合X.509国际标准。
目前X.509有不同的版本,例如X.509V2和x.509v3都是目前比较新的版本,2000年还推出V4版本,但是都在原有版本基础上进行功能的扩充,其中每一版本必须包含下列信息:(1)用来区分X.509的不同版本号既版本号(2)由CA给予每一个证书的分配的编号即序列号;(3)用于产生证书所用的方法以及一切参数即签名算法(4) CA的x.500名字即发出该证书的认证机构(5)证书有效的时间包括两个日期,在所指定的两个时间之间有效即有效期限(6)证书持有人的姓名、服务处所等信息即主题信息(7)认证机构的数字签名(8)被证明的公钥值,加上使用这个公钥的方法名称即公钥信息【X.509证书格式】X.509是另一种非常通用的证书格式。
所有的证书都符合ITU-T X.509国际标准;因此(理论上)为一种应用创建的证书可以用于任何其他符合X.509标准的应用。
但实际上,不同的公司对X.509证书进行了不同的扩展,不是所有的证书都彼此兼容。
在一份证书中,必须证明公钥及其所有者的姓名是一致的。
对PGP 证书来说,任何人都可以扮演认证者的角色。
对X.509证书来说,认证者总是CA或由CA指定的人(其实PGP证书也完全支持使用CA来确认证书的体系结构),一份X.509证书是一些标准字段的集合,这些字段包含有关用户或设备及其相应公钥的信息。
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有关大数运算函数列表
void BN_clear_free(BIGNUM *a); 相当与将BN_free和BN_clear综合,要不就赋值0,要不就释放空间。
2.上下文情景函数,存储计算中的中间过程
BN_CTX *BN_CTX_new(void);申请一个新的上下文结构
BIGNUM *rem, void (*callback)(int, int, void *), void *cb_arg);产生一个bits位的素数,后面几个参数都可以为NULL
int BN_is_prime(const BIGNUM *p, int nchecks,
void (*callback)(int, int, void *), BN_CTX *ctx, void *cb_arg);
6.比较函数
int BN_cmp(BIGNUM *a, BIGNUM *b); -1 if a < b, 0 if a == b and 1 if a > b.
int BN_ucmp(BIGNUM *a, BIGNUM *b); 比较a,b觉得值,返回值和上同。
int BN_is_zero(BIGNUM *a);
char *BN_bn2hex(const BIGNUM *a);转化为16进制字符串
char *BN_bn2dec(const BIGNUM *a);转化为10进制字符串
int BN_hex2bn(BIGNUM **a, const char *str);同上理
int BN_dec2bn(BIGNUM **a, const char *str);同上理
Linux下C语言使用openssl库进行加密
Linux下C语⾔使⽤openssl库进⾏加密 在这⾥插⼀⼩节加密的吧,使⽤openssl库进⾏加密。
使⽤MD5加密 我们以⼀个字符串为例,新建⼀个⽂件filename.txt,在⽂件内写⼊hello ,然后在Linux下可以使⽤命令md5sum filename.txt计算md5值==> b1946ac92492d2347c6235b4d2611184 。
虽然写⼊的是hello这5个字符,但是我们使⽤命令xxd filename.txt后可以看出⽂件结尾处会有个0x0a这个回车符。
所以在下⾯的代码中才会有\n。
1//打开/usr/include/openssl/md5.h这个⽂件我们可以看到⼀些函数2// 初始化 MD5 Contex, 成功返回1,失败返回03int MD5_Init(MD5_CTX *c);4// 循环调⽤此函数,可以将不同的数据加在⼀起计算MD5,成功返回1,失败返回05int MD5_Update(MD5_CTX *c, const void *data, size_t len);6// 输出MD5结果数据,成功返回1,失败返回07int MD5_Final(unsigned char *md, MD5_CTX *c);8// MD5_Init,MD5_Update,MD5_Final三个函数的组合,直接计算出MD5的值9 unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md);10// 内部函数,不需要调⽤11void MD5_Transform(MD5_CTX *c, const unsigned char *b); 新建⼀个cpp⽂件⽤于计算MD5值1 #include <openssl/md5.h>2 #include <string.h>3 #include <stdio.h>45int main()6 {7 MD5_CTX ctx;8 unsigned char outmd[16];9int i=0;1011 memset(outmd,0,sizeof(outmd));12 MD5_Init(&ctx);13 MD5_Update(&ctx,"hel",3);14 MD5_Update(&ctx,"lo\n",3);15 MD5_Final(outmd,&ctx);16for(i=0;i<16;i<i++)17 {18 printf("%02X",outmd[i]);19 }20 printf("\n");21return0;22 } 编译选项为: g++ MD5test.cpp -lssl -o MD5test 运⾏后的结果为: B1946AC92492D2347C6235B4D2611184 注意这⾥⽤到openssl库,可以运⾏ yum install openssl 和 yum install openssl-devel 进⾏安装。
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验证过了。
use_certificate_chain_file
use_certificate_chain_file#客户端请求时验证服务器端证书。
SSL_CTX_set_verify。
#载入随机数文件。
SSL_CTX_load_verify_locations。
#使用一般认证。
SSL_CTX_use_RSAPrivateKey_file。
#用文件载入CA证书。
SSL_CTX_load_verify_locations。
```。
# OpenSSL编程实例。
下面实例使用了 OpenSSL 库函数来编写一个客户端和一个服务端程序,它们使用 SSL 建立一条安全的虚拟管道,在这条管道里可以进行安全的数据交换。
##客户端程序。
以下程序示例是一个客户端程序,它通过SSL连接到一个服务器:```c。
#include <stdio.h>。
#include <unistd.h>。
#include <sys/socket.h>。
#include <arpa/inet.h>。
#include <openssl/ssl.h>。
#include <openssl/err.h>。
int main(int argc, char *argv[])。
int sockfd = 0;。
struct sockaddr_in serv_addr;。
char *hello = "Hello from client";。
char buffer[1024] = {0};。
SSL_CTX *ctx;。
SSL *ssl;。
/*SSL库初始化*/。
SSL_library_init();。
/*载入所有SSL算法*/。
OpenSSL_add_all_algorithms();。
/*载入所有SSL错误消息*/。
SSL_load_error_strings();。
/* 以 SSL V2 和 V3 标准兼容方式产生一个 SSL_CTX ,即 SSL Content Text */。
C#中使用OpenSSL的公钥加密私钥解密
C#中使⽤OpenSSL的公钥加密私钥解密在C#中进⾏公钥加密/私钥解密,需要⽤RSACryptoServiceProvider,但是它不⽀持由OpenSSL⽣成的公钥/私钥字符串。
公钥-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7PyjMEuniN6BPn8oqzIZ6AO1NjSTO9R3adCCIwKfKIEoWXXM+tHDpktdPKSaAsWJPTNAGvEvtxOfzXib/EMXKqD0eUy5MatfpRjRdf1hJVimmfrb09Qx2j7CsKLy7nD23m4xubdYBwvkjMwt/L3JxB5D6qryW1wei/j1c+/OCxQIDAQAB-----END PUBLIC KEY-----私钥-----BEGIN RSA PRIVATE KEY-----MIICXQIBAAKBgQC7PyjMEuniN6BPn8oqzIZ6AO1NjSTO9R3adCCIwKfKIEoWXXM+tHDpktdPKSaAsWJPTNAGvEvtxOfzXib/EMXKqD0eUy5MatfpRjRdf1hJVimmfrb09Qx2j7CsKLy7nD23m4xubdYBwvkjMwt/L3JxB5D6qryW1wei/j1c+/OCxQIDAQABAoGAT7vGYJgRNf4f6qgNS4pKHTu10RcwPFyOOM7IZ9M5380+HyXuBB6MEjowKwpH1fcy+LepwaR+5KG7b5uBGY4H2ticMtdysBd9gLwnY4Eh4j7LCWE54HvELpeWXkWpFQdb/NQhcqMAGwYsTnRPdBqkrUmJBTYqEGkIlqCQ5vUJOCECQQDhe0KGmbq1RWp6TDvgpA2dUmlt2fdP8oNW8O7MvbDaQRduoZnVRTPYCDKfzFqpNXL1hAYgth1N0vzDnv3VoLcpAkEA1JcY+rLv5js1g5Luv8LaI5/3uOg0CW7fmh/LfGuz8k/OxASN+cAOUjPHrxtc5xn1zat4/bnV5GEdlOp/DhquPQJBAIV2Fsdi4M+AueiPjPWHRQO0jvDVjfwFOFZSn5YSRUa6NmtmPY6tumUJXSWWqKb1GwlVTuc3xBqXYsNLLUWwLhkCQQDJUJCiD0LohhdGEqUuSKnj5H9kxddJO4pZXFSI7UEJbJQDwcBkyn+FTm2BH+tZGZdQfVnlA89OJr0poOpSg+eNAkAKY85SR9KASaTiDBoPpJ8N805XEhd0Kq+ghzSThxL3fVtKUQLiCh7Yd8oMd/G5S3xWJHUXSioATT8uPRH2bOb/-----END RSA PRIVATE KEY-----⽹上有⽜⼈通过解析公钥/私钥字符串,将之导⼊到RSACryptoServiceProvider中(原⽂链接已不存在)。
openssl ecc编程示例的编译命令
要编译使用OpenSSL ECC (Elliptic Curve Cryptography) 的程序,您需要确保已经安装了OpenSSL 库,并且使用适当的编译命令。
以下是一个示例程序和编译命令:```c#include <stdio.h>#include <openssl/ec.h>#include <openssl/err.h>int main() {// 创建ECC 密钥对EC_KEY *key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);if (key == NULL) {printf("Failed to create ECC key pair\n");return 1;}// 生成随机私钥if (!EC_KEY_generate_key(key)) {printf("Failed to generate ECC private key\n");EC_KEY_free(key);return 1;}// 获取公钥ECPublicKey pubKey;EC_KEY_set_public_key(key, &pubKey);// 打印公钥和私钥printf("Public key: ");BN_print_fp(stdout, EC_KEY_get0_public_key(key)); printf("\n");printf("Private key: ");BN_print_fp(stdout, EC_KEY_get0_private_key(key)); printf("\n");// 释放密钥对和错误队列EC_KEY_free(key);ERR_free_strings();return 0;}```要编译这个示例程序,您可以使用以下命令:```bashgcc -o ecc_example ecc_example.c -lcrypto -lgmp -ldl```这将使用GCC 编译器编译名为`ecc_example.c` 的源文件,并将输出文件命名为`ecc_example`。
openssl实验
openssl实验会用opensll.exe应用程序指令参阅两个文档《openssl编程第32章》和《openssl应用程序指令》rand 生成随机数生成随机数。
用法:openssl rand [-out file] [-rand file(s)] [-base64] num选项:-out file结果输出到file中。
-engine e采用engine来生成随机数。
-rand file指定随机数种子文件。
-base64输出结果为BASE64编码数据。
num随机数长度。
示例:(1) openssl rand –base64 100(2)openssl rand –base64 –out myr.dat 100用WinHex或UltraEdit打开myr.datspeedspeed命令用于测试库的性能。
用法:openssl speed [-engine id] [md2] [mdc2] [md5] [hmac] [sha1] [rmd160] [idea-cbc] [rc2-cbc] [rc5-cbc] [bf-cbc] [des-cbc] [des-ede3] [rc4][rsa512] [rsa1024] [rsa2048] [rsa4096] [dsa512] [dsa1024][dsa2048][idea] [rc2] [des] [rsa] [blowfish]选项:-engine id设置硬件引擎id。
-elapsed测量采用实时时间,不是所用CPU时间,两者时间差异较大。
-mr生成机器可读显示。
-multi n并行允许n个测试。
示例:openssl speed md5Prime检查一个数是否为素数。
示例如下:openssl prime 79openssl prime -hex 4Fencenc为对称加解密工具,还可以进行base64编码转换。
用法:openssl enc -ciphername [-in filename] [-out filename] [-pass arg] [-e ] [-d ] [-a ] [-A] [-k password ] [-kfile filename] [-K key] [-iv IV] [-p] [-P] [-bufsize number] [-nopad] [-debug] 选项:-ciphername对称算法名字,此命令有两种适用方式:-ciphername方式或者省略enc直接用ciphername。
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编程赵春平著Email: forxy@第⼀章基础知识 81.1 对称算法 81.2 摘要算法 91.3 公钥算法 91.4 回调函数 11第⼆章 openssl简介 132.1 openssl简介 132.2 openssl安装 132.2.1 linux下的安装 132.2.2 windows编译与安装 142.3 openssl源代码 142.4 openssl学习⽅法 16第三章堆栈 173.1 openssl堆栈 173.2 数据结构 173.3 源码 183.4 定义⽤户⾃⼰的堆栈函数 183.5 编程⽰例 19第四章哈希表 214.1 哈希表 214.2 哈希表数据结构 214.3 函数说明 234.4 编程⽰例 25第五章内存分配 275.1 openssl内存分配 275.2 内存数据结构 275.3 主要函数 285.4 编程⽰例 29第七章抽象IO 347.1 openssl抽象IO 347.2 数据结构 347.3 BIO 函数 367.4 编程⽰例 367.4.1 mem bio 367.4.2 file bio 377.4.3 socket bio 387.4.4 md BIO 397.4.5 cipher BIO 407.4.6 ssl BIO 417.4.7 其他⽰例 42第⼋章配置⽂件 438.1 概述 438.2 openssl配置⽂件读取 438.3 主要函数 448.4 编程⽰例 44第九章随机数 469.1 随机数 469.2 openssl随机数数据结构与源码 46 9.3 主要函数 489.4 编程⽰例 48第⼗章⽂本数据库 5010.1 概述 5010.2 数据结构 5110.3 函数说明 5110.4 编程⽰例 52第⼗⼀章⼤数 5411.1 介绍 5411.2 openssl⼤数表⽰ 5411.3 ⼤数函数 5511.4 使⽤⽰例 58第⼗⼆章 BASE64编解码 6412.1 BASE64编码介绍 6412.2 BASE64编解码原理 6412.3 主要函数 6512.4 编程⽰例 66第⼗三章 ASN1库 6813.1 ASN1简介 6813.2 DER编码 7013.3 ASN1基本类型⽰例 7013.4 openssl 的ASN.1库 7313.5 ⽤openssl的ASN.1库DER编解码 74 13.6 Openssl的ASN.1宏 7413.7 ASN1常⽤函数 7513.8 属性证书编码 89第⼗四章错误处理 9314.1 概述 9314.2 数据结构 9314.3 主要函数 9514.4 编程⽰例 97第⼗五章摘要与HMAC 100第⼗六章数据压缩 10416.1 简介 10416.2 数据结构 10416.3 函数说明 10516.4 openssl中压缩算法协商 106 16.5 编程⽰例 106第⼗七章 RSA 10717.1 RSA介绍 10717.2 openssl的RSA实现 107 17.3 RSA签名与验证过程 108 17.4 数据结构 10917.4.1 RSA_METHOD 109 17.4.2 RSA 11017.5 主要函数 11017.6编程⽰例 11217.6.1密钥⽣成 11217.6.2 RSA加解密运算 113 17.6.3签名与验证 116第⼗⼋章 DSA 11918.1 DSA简介 11918.2 openssl的DSA实现 120 18.3 DSA数据结构 12018.4 主要函数 12118.5 编程⽰例 12218.5.1密钥⽣成 12218.5.2签名与验证 124第⼗九章DH 12619.1 DH算法介绍 12619.2 openssl的DH实现 127 19.3数据结构 12719.4 主要函数 12819.5 编程⽰例 129第⼆⼗章椭圆曲线 13220.1 ECC介绍 13220.2 openssl的ECC实现 133 20.3 主要函数 13520.3.1参数设置 13520.3.2参数获取 13620.3.3转化函数 13720.3.4其他函数 13720.4 编程⽰例 139第⼆⼗⼀章 EVP 14321.1 EVP简介 14321.2 数据结构 14321.2.1 EVP_PKEY 14421.2.2 EVP_MD 14421.2.3 EVP_CIPHER 14521.2.4 EVP_CIPHER_CTX 146 21.3 源码结构 14721.4 摘要函数 14721.5 对称加解密函数 14821.6 ⾮对称函数 149第⼆⼗⼆章 PEM格式 15922.1 PEM概述 15922.2 openssl的PEM实现 16022.3 PEM函数 16122.4 编程⽰例 161第⼆⼗三章 Engine 16523.1 Engine概述 16523.2 Engine⽀持的原理 16523.3 Engine数据结构 16623.4 openssl 的Engine源码 16723.5 Engine函数 16723.6 实现Engine⽰例 169第⼆⼗四章通⽤数据结构 18224.1通⽤数据结构 18224.2 X509_ALGOR 18224.3 X509_VAL 18424.4 X509_SIG 18524.5 X509_NAME_ENTRY 18624.6 X509_NAME 18724.7 X509_EXTENSION 19324.8 X509_ATTRIBUTE 19924.9 GENERAL_NAME 200第⼆⼗五章证书申请 20325.1 证书申请介绍 20325.2 数据结构 20325.3 主要函数 20425.4 编程⽰例 20625.4.1⽣成证书请求⽂件 20625.4.2 解码证书请求⽂件 208第⼆⼗六章 X509数字证书 21026.1 X509数字证书 21026.2 opessl实现 21026.3 X509数据结构 21026.4 X509_TRUST与X509_CERT_AUX 214 26.5 X509_PURPOSE 21526.6 主要函数 21826.7 证书验证 22126.7.1证书验证项 22126.7.2 Openssl中的证书验证 221第⼆⼗七章 OCSP 22227.1 概述 22227.2 openssl实现 22227.3 主要函数 22227.4编程⽰例 227第⼆⼗⼋章 CRL 22828.1 CRL介绍 22828.2 数据结构 22828.3 CRL函数 23028.4 编程⽰例 231第⼆⼗九章 PKCS7 23329.1概述 23329.2 数据结构 23329.3 函数 23429.4.4 signed_and_enveloped 238 29.4.5 digest 23829.4.6 encrypted 23929.4.7 读取PEM 23929.4.8 解码pkcs7 240第三⼗章 PKCS12 24130.1 概述 24130.2 openss实现 24130.3数据结构 24230.4函数 24330.5 编程⽰例 245第三⼗⼀章 SSL实现 25431.1概述 25431.2 openssl实现 25431.3 建⽴SSL测试环境 25431.4 数据结构 25631.5 加密套件 25631.6 密钥信息 25731.7 SESSION 25831.8 多线程⽀持 25831.9 编程⽰例 25931.10 函数 270第三⼗⼆章 Openssl命令 272 32.1概述 27232.2 asn1parse 27232.3 dgst 27432.4 gendh 27532.5 passwd 27632.6 rand 27632.7 genrsa 27732.8 req 27832.9 x509 28032.10 version 28332.11 speed 28332.12 sess_id 28432.13 s_server 28432.14 s_client 28632.15 rsa 28832.16 pkcs7 28932.17 dsaparam 29032.18 gendsa 29132.19 enc 29132.20 ciphers 29232.21 CA 29332.22 verify 29632.23 rsatul 29732.24 crl 29932.25 crl2pkcs7 30032.26 errstr 30032.27 ocsp 30132.28 pkcs12 30432.29 pkcs8 30632.30 s_time 30732.35 nseq 31232.36 prime 31332.37 smime 313第⼀章基础知识1.1 对称算法对称算法使⽤⼀个密钥。
openssl 编程入门(含完整示例)
openssl编程入门(含完整示例)易剑1.编写目的第一次跑起openssl示例并不太简单,本文的目的是为了让这个过程变得非常简单。
在开始之前,要非常感谢周立发同学,正是通过他共享的示例,较轻松的入了门。
本文档对他共享的示例中的一个小错误进行了修正,并提供了傻瓜式的“编译-生成-KEY运行”一条龙脚本(方法请参见压缩包中的readme文件),让跑第一个openssl程序变得轻轻松松。
2.示例包ssl_test.tar.gz openssl-0.9.8h-SuSE10.tar.gzssl_test.tar.gz为示例源代码包,openssl-0.9.8h-SuSE10.tar.gz为openssl二进制包,测试时是安装在/usr/local/ssl。
ssl_test.tar.gz中的示例在SuSE10中测试通过,使用的是openssl-0.9.8h,它包括如下文件:-rw-r--r--1root root1346Dec518:11cacert.pem-rwxr-xr-x1root root114Dec518:11make_key.sh-rwxr-xr-x1root root172Dec518:37mk_client.sh-rwxr-xr-x1root root172Dec518:37mk_server.sh-rw-r--r--1root root1679Dec518:11privkey.pem-rw-r--r--1root root167Dec518:39readme-rwxr-xr-x1root root38Dec518:38run_client.sh-rwxr-xr-x1root root64Dec518:38run_server.sh-rwxr-xr-x1root root1140142Dec518:38ssl_client-rw-r--r--1root root3928Dec517:31ssl_client.cpp-rwxr-xr-x1root root1139667Dec518:38ssl_server-rw-r--r--1root root4882Dec517:31ssl_server.cppreadme为包内容说明,run_server.sh用来运行服务端,run_client.sh用来运行客户端,mk_server.sh用来编译服务端,mk_client.sh用来编译客户端,make_key.sh用来生成钥匙KEY。
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进行SSL编程
用openssl进行SSL编程主要介绍openssl进行ssl通信的一些函数以及过程,主要是初始化过程,至于数据的接收以及后续处理可以具体问题具体分析。
load所有的ssl算法openssl_add_ssl_algorithms();建立ssl所用的methodssl_method *meth=sslv23_method();初始化上下文情景ssl_ctx *ctx=ssl_ctx_new(meth);ret->quiet_shutdown=1;默认的是ret->quiet_shutdown=0;他相当于ssl_set_shutdown函数将参数设置为ssl_sent_shutdown|ssl_received_shutdown当设置为1时,假如关闭后,不通知对方,这样不适合tls标准ssl_ctx_set_quiet_shutdown(ctx,1);ctx->options|=ssl_op_all,ssl/tls有几个公认的bug,这样设置会使出错的可能更小ssl_ctx_set_options(ctx,ssl_op_all);设置cache的大小,默认的为1024*20=20000,这个也就是可以存多少个session_id,一般都不需要更改的。
假如为0的话将是无限ssl_ctx_sess_set_cache_size(ctx,128);ssl_ctx_load_verify_locations用于加载受信任的ca证书,cafile 如果不为null,则他指向的文件包含pem编码格式的一个或多个证书,可以用e.g.来简要介绍证书内容capath如果不为null,则它指向一个包含pem格式的ca证书的目录,目录中每个文件包含一份ca证书,文件名是证书中ca名的hash值可以用c-rehash来建立该目录,如cd /some/where/certs(包含了很多可信任的ca证书)c_rehash .。
OpenSSL 中文手册
OpenSSL 中文手册之一OpenSSL 简介-证书2011-05-13 11:52 44人阅读评论(0) 收藏举报证书就是数字化的文件,里面有一个实体(网站,个人等)的公共密钥和其他的属性,如名称等。
该公共密钥只属于某一个特定的实体,它的作用是防止一个实体假装成另外一个实体。
证书用来保证不对称加密算法的合理性。
想想吧,如果没有证书记录,那么假设某俩人A 与B的通话过程如下:这里假设A的publickey是K1,privatekey是K2,B的publickey是K3,privatekey是K4 xxxxxx(kn)表示用kn加密过的一段文字xxxxxxA-----〉hello(plaintext)-------------〉BA〈---------hello(plaintext)〈---------BA〈---------Bspublickey〈------------BA---------〉spublickey(K1)--------〉B......如果C想假装成B,那么步骤就和上面一样。
A-----〉hello(plaintext)-------------〉CA〈---------hello(plaintext)〈---------C注意下一步,因为A没有怀疑C的身份,所以他理所当然的接受了C的publickey,并且使用这个key来继续下面的通信。
A〈---------Cspublickey〈------------CA---------〉Aspublickey(K1)--------〉C......这样的情况下A是没有办法发觉C是假的。
如果A在通话过程中要求取得B的证书,并且验证证书里面记录的名字,如果名字和B的名字不符合,就可以发现对方不是B.验证B的名字通过再从证书里面提取B的公用密钥,继续通信过程。
那么,如果证书是假的怎么办?或者证书被修改过了怎么办?慢慢看下来吧。
证书最简单的形式就是只包含有证书拥有者的名字和公用密钥。
openssl编译方法
openssl编译⽅法
受不了了,终于编译成功了openssl,写⼀下编译⽅法吧
准备:
0:要编译openssl,必不可少的是代码,去下载
1:要有⼀个VS系列编译器,只要是能开VS命令⾏的就⾏,⽐如VS2013,带命令⾏的应该都⾏。
没有就去微软官⽹下载
2:nasm,直接去下载就⾏了,可以下载安装包,如果下载zip包的话,要⼿动加nasm的⽬录到环境变量path⾥⾯3:perl,我就不知道为什么这帮家伙们都这么喜欢这个东西,这脚本很好么,去下载,然后安装
解压了openssl,
安装了nasm,
安装了perl,
打开vs命令⾏,
切换到openssl⽬录,
输⼊ perl Configure VC-WIN32 ,
如果没有错误,配置成功的话,openssl⽬录下会出现⼀个makefile,
输⼊ nmake -f makefile,
开编
⼀堆乱七⼋糟的编译信息,等着,等它们结束了之后
可以再输⼊ nmake test
然后看输出的信息确定是否编译成功,
编译成功之后的头⽂件,在include ⽬录中,
lib 和dll 就在当前⽬录中。
OK,结束了。
补上⼀句,如果需要编译静态库⼯程,那么在 perl Configure VC-WIN32 阶段加参数 -static 就可以了,
具体参数列表,configure⽂件有明确写出。
listenandservetls memory
listenandservetls memory在使用gRPC框架中,可以使用go语言的net包中的ListenAndServeTLS函数来实现使用TLS协议进行安全传输的服务器监听。
ListenAndServeTLS函数的函数签名如下所示:```gofunc ListenAndServeTLS(addr, certFile, keyFile string, handler http.Handler) error```其中,addr参数指定服务器监听的地址,certFile参数指定TLS证书文件的路径,keyFile参数指定TLS私钥文件的路径,handler参数指定处理传入连接的处理器。
为了使用TLS协议,我们需要生成并配置相应的证书和私钥文件。
在实际的应用中,我们可以通过使用openssl生成自签名证书来进行开发和测试。
具体的操作如下所示:1. 生成私钥文件```bash$ openssl genrsa -out server.key 2048```2. 生成证书签名请求(CSR)```bash$ openssl req -new -key server.key -out server.csr```在生成CSR时,根据提示输入相关信息。
3. 自签名证书```bash$ openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt```以上命令将使用私钥文件(server.key)对CSR文件(server.csr)进行签名,生成自签名证书文件(server.crt)。
在生成证书和私钥文件后,我们可以在代码中使用ListenAndServeTLS函数来进行TLS服务器监听。
下面是一个简单示例代码:```gopackage mainimport ("crypto/tls""log""net/http")func main() {mux := http.NewServeMux()// 注册处理器函数mux.HandleFunc("/", func(w http.ResponseWriter, r*http.Request) {w.Write([]byte("Hello, gRPC!"))})// 创建服务器server := &http.Server{Addr: ":8080",Handler: mux,}// 加载证书和私钥cert, err := tls.LoadX509KeyPair("server.crt", "server.key") if err != nil {log.Fatal(err)}// 配置TLSconfig := &tls.Config{Certificates: []tls.Certificate{cert},}// 监听并提供安全传输err = server.ListenAndServeTLS("", "", "server.crt", "server.key")if err != nil {log.Fatal(err)}}```在代码中,我们首先创建了一个处理器函数,然后创建了一个新的ServeMux和一个http.Server。
d2i_rsapublickey 例子
d2i_RSAPublicKey是 OpenSSL 库中用于将 DER 格式的 RSA 公钥数据转换为 RSA 公钥对象的函数。
以下是一个简单的例子,演示如何使用 OpenSSL 中的
d2i_RSAPublicKey函数。
在这个例子中,我们将使用 OpenSSL 的函数来读取包含 RSA 公钥信息的 DER 文件,并将其转换为RSA结构。
请注意,这个例子假设你已经有一个包含 RSA 公钥信息的 DER 文件(例如,通过openssl rsa -pubout -outform DER -in private_key.pem -out public_key.der创建)。
在实际使用中,你需要根据你的情况进行相应的修改,确保文件路径和格式正确。
此外,这个例子中没有错误处理,实际应用中应该根据需要添加适当的错误检查和处理机制。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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要求客户端提供证书,// 如果不提供的话,则校验失败。