本文将给出数个用于生成SSL证书的bat脚本,并探讨当不需要身份验证时可行的简化方案。
本文面向openssl初学者,但需要一定的密码学基础知识。具体包括 对称加密、非对称加密、密钥、公钥、数字证书,以上概念只需了解即可。
本文假设你已经下载安装了openssl,文章内容将不包含安装openssl。打开CMD输入openssl来验证你的openssl是否可以正常使用。
windows10 Visual Studio 2010 C++ openssl-1.1.0h
假设我们的需求是TCP通信,C/S结构,只考虑单客户端单一身份,SSL加密,双向身份验证。
在你希望存放证书的地方创建一个文件夹,笔者本次做实验选择 D:\temp\test ,本文使用"test文件夹"指代该文件夹。
在test文件夹中创建名为key的空文件夹。这个后面会用到。
在test文件夹中创建名为certs和newcerts的2个空文件夹。这个后面不会用到,但没他们openssl可能会报错。
找到openssl安装目录,就是安装openssl时makefile、INSTALL所在的目录,大概长这样:
需要注意的是里面的apps文件夹,下一步要用到。
将 openssl安装目录\apps 下的openssl.cnf复制到test文件夹下。
将 openssl安装目录\apps\demoCA 下的index.txt、serial两个文件复制到test文件夹下。
修改openssl.cnf(指test文件夹下的文件,下同),将dir变量的值改为“.”。
dir = . # Where everything is kept
注意事项:
1、#后面是注释
2、openssl.cnf和demoCA文件夹的名字可能会随openssl版本的变化而变,可能会变成openssl.conf、demo等,随机应变吧。
3、笔者使用UltraEdit修改openssl.cnf,也可以用记事本或你喜欢的编辑器。
笔者推荐使用脚本执行下面的命令,如果你cmd玩的6也可以直接用cmd。
在test文件夹下创建client.bat和server.bat,内容如下:
client.bat ↓
openssl.exe genrsa -out key\client.key 1024
openssl.exe req -new -x509 -days 3650 -key key\client.key -out key\client.crt -config openssl.cnf
@pause
server.bat ↓
openssl.exe genrsa -out key\server.key 1024
openssl.exe req -new -x509 -days 3650 -key key\server.key -out key\server.crt -config openssl.cnf
@pause
执行这两个bat文件,会提示你输入一些参数,除了Common Name之外全部回车跳过,Common Name分别填testclient
和testserver。执行完毕后得到2个key文件和2个crt文件,全都在key文件夹里。
2个key文件是客户端和服务端的密钥文件,2个crt文件是客户端和服务端的自签名证书。自签名证书与SSL证书的关系不在本文的讨论范围内,此处略过。本文的最后会给出一个生成多种类型证书的脚本,仅供参考。
使用SSL_CTX_load_verify_locations函数加载信任证书
使用SSL_CTX_use_certificate_file函数加载证书
使用SSL_CTX_use_PrivateKey_file函数加载密钥(指私钥,下同)
具体到key文件夹里的4个文件,我们需要
在服务端使用SSL_CTX_load_verify_locations加载client.crt,使用SSL_CTX_use_certificate_file加载server.crt,使用SSL_CTX_use_PrivateKey_file加载server.key。
在客户端使用SSL_CTX_load_verify_locations加载server.crt,使用SSL_CTX_use_certificate_file加载client.crt,使用SSL_CTX_use_PrivateKey_file加载client.key。
注意事项:信任证书并不一定要与对方的证书相同,本例这么做是为了减少证书数量,快速上手openssl库。
加载完所有密钥和证书后,就可以按照正常TCP通信的流程建立连接,TCP连接建立后,使用SSL_accept和SSL_connect建立安全连接,在此过程中openssl会进行身份验证。再之后使用SSL_write和SSL_read进行加密通信。
假如不需要身份验证,我们的程序能否简化?能否不加载证书?
第一个问题的答案是肯定的,可以。关于第二个问题,笔者并没能使用openssl-1.1.0h实现,但我认为是可能的,有待深入研究。
简化的方法是:在服务端不调用SSL_CTX_load_verify_locations,使用SSL_CTX_use_certificate_file加载server.crt,使用SSL_CTX_use_PrivateKey_file函数加载server.key;在客户端使用SSL_CTX_load_verify_locations加载server.crt,不调用SSL_CTX_use_certificate_file和SSL_CTX_use_PrivateKey_file。
这样一来,证书和密钥的数量都减少到1个。
有趣的是,如果把服务端和客户端颠倒过来,在服务端使用SSL_CTX_load_verify_locations加载client.crt,在客户端使用SSL_CTX_use_certificate_file加载client.crt,使用SSL_CTX_use_PrivateKey_file加载client.key,则无法建立安全连接,SSL_connect会返回一个错误。
笔者认为,这可能与TLSv1_client_method函数有关。
openssl支持CA认证,下面的脚本可以创建CA认证证书:
openssl.exe genrsa -out key\ca.key -rand private\.rnd 2048
openssl.exe req -new -x509 -days 3650 -key key\ca.key -out key\ca.crt -config openssl.cnf
openssl.exe req -new -key key\server.key -out key\server.csr -config openssl.cnf
openssl.exe ca -in key\server.csr -cert key\ca.crt -keyfile key\ca.key -config openssl.cnf -policy policy_anything -out key\serverca.crt
openssl.exe req -new -key key\client.key -out key\client.csr -config openssl.cnf
openssl.exe ca -in key\client.csr -cert key\ca.crt -keyfile key\ca.key -config openssl.cnf -policy policy_anything -out key\clientca.crt
@pause
使用方法:客户端和服务端都使用ca.crt作为信任证书,clientca.crt和serverca.crt分别是客户端和服务端需要加载的证书,密钥文件用法不变。
注意事项:
1、这个脚本的运行依赖上文生成的2个key文件。
2、需要输入一些参数,除了Common Name之外全部可以回车跳过,Common Name需要填3次,第一次填CA认证机构的名字,第二次填服务器的名字,第三次填客户端的名字,做实验的话都可以随便填。如果询问y/n的话全部y。
-------------------EOB-----------------------------