SSL协议为了解决在网络中的实体认证和信息的加密传输,为了做到这两点,基于SSL协议的通信需要进行若干次的握手协商(点击查看),这么多的握手步骤概括来说分为三步:1.双方交换证书来确保彼此的身份;2.身份确认后进行会话通信密钥的协商(详见附录二);3.协商出会话密钥后用其进行加密传输信息。
Openssl是SSL协议的一个实现库,关于OpenSSL的功能与简介在此我就不多介绍了,详细可以观看我的另一篇博文:OpenSSL简介。
程序介绍及目的:
程序分为两部分,客户端和服务器端,我们的目的是利用SSL/TLS的特性保证通信双方能够互相验证对方身份(真实性),并保证数据的完整性, 私密性。
一、程序的框架:
1.客户端程序的框架为:
/*生成一个SSL结构*/
meth = SSLv23_client_method();
ctx = SSL_CTX_new (meth);
ssl = SSL_new(ctx);
/*下面是正常的socket过程*/
fd = socket();
connect();
/*把建立好的socket和SSL结构联系起来*/
SSL_set_fd(ssl,fd);
/*SSL的握手过程*/
SSL_connect(ssl);
/*接下来用SSL_write(), SSL_read()代替原有的write(),read()即可*/
SSL_write(ssl,"Hello world",strlen("HelloWorld!"));
2.服务端程序的框架为:
/*生成一个SSL结构*/
meth = SSLv23_server_method();
ctx = SSL_CTX_new (meth);
ssl = SSL_new(ctx);
/*下面是正常的socket过程*/
fd = socket();
bind();
listen();
accept();
/*把建立好的socket和SSL结构联系起来*/
SSL_set_fd(ssl,fd);
/*SSL的握手过程*/
SSL_connect(ssl);
/*接下来用SSL_write(), SSL_read()代替原有的write(),read()即可*/
SSL_read (ssl, buf, sizeof(buf));
对程序来说,openssl将整个握手过程用一对函数体现,即客户端的SSL_connect和服务端的SSL_accept.而后的应用层数据交换则用SSL_read和 SSL_write来完成.
二、证书文件生成
基于SSL协议的应用必然会涉及到数字证书,可以说二者必然同存亡,因为在网络中证明某个实体身份的只有数字证书,而ssl协议解决的问题之一就是要跟正确的人进行保密的信息传输,因此在确定对方就是正确的通信目标时只能用数字证书来验证,所以除将第一步的程序编译成功外,还需生成必要的证书和私钥文件使双方能够成功验证对方,步骤如下。1、前期准备:
在生成证书的目录(即:包含OpenSSL.exe文件的目录)下建立几个文件和文件夹,有
./demoCA/
./demoCA/newcerts/
./demoCA/private/
./demoCA/index.txt (空文件,生成证书时会将数据记录写入)
./demoCA/serial (在serial文件中写入第一个序列号“01”,在生成证书时会以此递增)或在openssl的配置文件中搜索这个文件拷贝到这里。
安装完成后将openssl\bin添加到环境变量path中,可方便使用
注意:cnf扩展名会被操作系统当成快捷方式,看不到扩展名,在dos下使用dir就可以看到。
进入cmd后输入openssl可能会提示
WARNING: can't open config file: /usr/local/ssl/openssl.cnf
提示找不到openssl.cnf ,没有关系在输入openssl命令前添加环境变量OPENSSL_CONF即可。
set OPENSSL_CONF=openssl.cnf
一般使用openssl.cnf默认配置即可无需修改。openssl.cnf文件在bin目录里,但是其样例文件一般会以.cfg或.example等作后缀,更改过来即可。
用户进行证书申请:一般先生成一个私钥,然后用私钥生成证书请求(证书请求里应含有公钥信息),再利用证书服务器的根证书来签发证书。
特别说明:
(1)自签名证书(一般用于顶级证书、根证书): 证书的名称和认证机构的名称相同.(2)根证书:根证书是CA认证中心给自己颁发的证书,是信任链的起始点。安装根证书意味着对这个CA认证中心的信任
数字证书是由证书认证机构(CA)对证书申请者真实身份验证之后,用CA的根证书对申请人的一些基本信息以及申请人的公钥进行签名(相当于加盖发证书机构的公章)后形成的一个数字文件。数字证书包含证书中所标识的实体的公钥(就是说你的证书里有你的公钥),由于证书将公钥与特定的个人匹配,并且该证书的真实性由颁发机构保证(就是说可以让大家相信你的证书是真的),因此,数字证书为如何找到用户的公钥并知道它是否有效这一问题提供了解决方案。
openssl中有如下后缀名的文件:
.key格式:私有的密钥
.csr格式:证书签名请求(证书请求文件),含有公钥信息,certificate signing request的缩写
.crt格式:证书文件,certificate的缩写
.crl格式:证书吊销列表,Certificate Revocation List的缩写
.pem格式:用于导出,导入证书时候的证书的格式,有证书开头,结尾的格式
常用证书协议:
x.500: 目录的标准
SCEP: 简单证书申请协议,用http来进行申请,数据有PKCS#7封装,数据格式其实也是PKCS#10。
PKCS#7:是封装数据的标准,可以放置证书和一些请求信息,关于P7及下面设计到的P10和P12在Openssl里面其实就是一个结构体,可以查看这些结构体加以理解。
PKCS#10:用于离线证书申请的证书申请的数据格式,证书申请者产生一个密码对,将公钥组织到P10结构中并用私钥对其进行签名,将签名值也组织到P10结构中,在Openssl里面对应的结构体是X509_REQ,注意数据包是使用PKCS#7封装这个数据。
PKCS#12:用于一个单一文件中交换公共和私有对象,就是公钥,私钥和证书,这些信息进行打包,加密放在存储目录中,CISCO放在NVRAM中,用户可以导出,以防证书服务器挂掉可以进行相应恢复。思科是.p12,微软是.pfx.
这一部分非常关键,涉及到证书的形成,我当初耗时很久才解决这些证书文件,希望学习者慢慢调试,如有问题欢迎交流:2006sszgg@163.com.
三、代码实现(win32版本)
代码我已经上传,学习的朋友欢迎去下载
中间输入的密码统一都是:123456.我已经测试过,可以运行。
四、SSL/TLS中的密钥:
在HTTPS协议中,客户端与服务端进行对称的对话密钥协商过程中,为嘛需要三个随机数来生成”会话密钥”,dog250解释得很好:“不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于SSL协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。对于RSA密钥交换算法来说,pre-master-key本身就是一个随机数,再加上hello消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。
pre master key的存在在于SSL协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么pre master secret就有可能被猜出来,那么仅适用pre master secret作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上pre master secret三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。”
预主密钥、主密钥和会话密钥,这几个密钥都是有联系的。
对于RSA来说,预主密钥是客户端生成,加密之后发给服务器,服务器用私钥来解密。
对于ECDHE来说,预主密钥是双方通过椭圆曲线算法来生成。主密钥是由预主密钥、客户端随机数和服务器随机数通过PRF函数来生成;会话密钥是由主密钥、客户端随机数和服务器随机数通过PRF函数来生成,会话密钥里面包含对称加密密钥、消息认证和CBC模式的初始化向量,但对于非CBC模式的加密算法来说,就没有用到这个初始化向量。
附录一.参考文献有
1.openssl 生成证书【整理】
2.pdf文档ssl与tsl.
3.解密https的建立过程
附录二.对称密钥协商相关的文章
1.Https SSL/TLS PreMaster/MasterSecret(Key)计算
2.Premaster secret and master key in OpenSSL
3.让SSL/TLS协议流行起来:深度解读SSL/TLS实现
4.扫盲 HTTPS 和 SSL/TLS 协议[3]:密钥交换(密钥协商)算法及其原理
5. 一个简单的DH密钥协商算法的实现
6.SM2算法第二十二篇:DH与ECDH秘钥协商原理
7. HTTPS 协议和原理
8.基于TLS1.3的微信安全通信协议mmtls介绍
9.https会话过程中密钥的计算