简介
- 1995年,Eric Andrew Young 和 Tim J. Hudson 开发了 SSLeay。这是一个开源的SSL实现,它支持X.509v3证书、PKCS#10证书请求、SSL2和SSL3。(注:eay是Eric Andrew Young的首字母)
- 1998年,OpenSSL项目启动,它基于SSLeay的代码进行开发。
OpenSSL可以分成三个主要部分:
- 密码算法库:实现了目前大部分主流的密码算法和标准。主要包括对称算法、非对称算法、散列算法、数字签名和认证、X509数字证书标准、PKCS12、PKCS7等标准。
- SSL协议库:完全实现SSL协议和TLS协议。
- 命令行工具:基于密码算法库和SSL协议库实现的命令。包括各种算法的加密程序和各种类型密钥的产生程序、证书签发和验证程序、SSL连接测试程序等。
版本
在Qt中碰到的几个版本(注:3.0开始版本规则又发生改变,版本号不再用字母后缀):
版本 | 初始发布日期 | 备注 |
---|---|---|
1.0.2 | 2015年1月22日 | 1.0.2u(2019年12月20日) |
1.1.1 | 2018年9月11日 | 1.1.1w(2023年9月11日) |
3.0 | 2021年9月7日 | (2026年9月7日) |
注:OpenSSL1.1和OpenSSL1.0二进制和源码都不兼容
动态库名称
OpenSSL库包含两个动态库(共享库)文件:
- libssl
- libcrypto
前者实现ssl的基本功能,后者是各种加密算法。
OpenSSL1.1之前的版本,在Windows下用MSVC编译的产物,名字比较怪异,是:
- ssleay32 (等价于 libssl32)
- libeay32
初次见到它是在Windows下,有些懵
好消息是,从OpenSSL1.1开始,在Windows下的命名也规范统一了
libssl-1_1(-x64).dll
libcrypto-1_1(-x64).dll
命令行工具
OpenSSL支持的命令列表,可以通过openssl help
查看
1 |
|
它会返回内容很长,包括:
标准命令列表
1 2 3 4 5 |
|
摘要命令
1 2 3 4 |
|
以及
1 2 3 4 |
|
算法
对称加密算法(Cipher)
特点是文件加密和解密使用相同的密钥,即加密密钥也用作解密密钥。特点:加解密速度很快,但密钥丢失,会造成安全隐患。
- https://www.openssl.org/docs/man1.1.1/man1/enc.html
通过openssl enc -list
命令可以获取算法列表
- AES
- Blowfish
- Camelia
- Poly1305
- SEED
- CAST-128
- DES
- IDEA
- RC2
- RC4
- RC5
- Triple DES
- GOST 28147-89
- SM4
加解密使用
使用AES加密:
1 |
|
解密
1 |
|
加解密过程中会提示输入密码,类似下面这样:
1 |
|
非对称加密算法(Public-key cryptography)
非对称加密算法需要两个密钥:公开密钥(public-key)和私有密钥 (private-key)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密(公私钥互为加解密关系)。
相对于对称加密算法来说,非对称加密算法速度很慢。
- RSA
- DSA
- Diffie-Heliman key exchange(迪菲-赫尔曼密钥交换)
- Elliptic curve(椭圆曲线)
- X25519
- Ed25519
- X448
- Ed448
- GOST R34.10-2001
- SM2
对非对称加密算法,一些知识点:
- 使用公钥操作数据(公钥加密,私钥解密) -> 加密
- 使用私钥对原文的摘要操作(私钥加密,公钥解密) -> 签名
- 公钥和私钥可以互相加密解密(对应上两条)
- 公钥对外公开,但私钥一定不能泄露。
密钥操作
OpenSSL3 默认生成密钥格式(PKCS#8)和之前(PKCS#1)不同。
直观差异体现在密钥文件的开头:
PKCS#1(只用于RSA)
1 |
|
和PKCS#8(也适用于其他算法的私钥,使用OID进行区分)
1 |
|
在OpenSSL3中,可以使用-traditional
选项来生成老的格式。
两个格式具体差异,详见:DER格式小结
OpenSSL 1.1下
生成密钥(PKCS#1格式)
1 2 3 4 5 6 |
|
查看私钥内容
1 2 3 4 5 6 7 8 |
|
- https://www.openssl.org/docs/man1.1.1/man1/openssl-pkcs8.html
PKCS#1到PKCS#8转换(-nocrypt生成不带密码的私钥)
1 |
|
PKCS#8 到PKCS#1转换
1 |
|
OpenSSL 3.0下
生成密钥(PKCS8格式):
1 2 3 4 5 6 |
|
查看密钥:
1 2 3 4 5 6 |
|
导出公钥:
1 2 3 4 5 6 7 8 |
|
注:-in -out 默认都是私钥,通过-pubout指定输出公钥;同样通过-pubin指定输入公钥。
PEM 与 DER转换
输出格式默认都是pem格式,如果要使用der格式,可以使用 -outform DER
指定:
1 |
|
加解密操作
使用公钥加密文件(openssl命令行只能使用公钥加密,其C API支持私钥加解密):
1 |
|
即使是如下这样写,还是用的私钥文件中的公钥进行的加密:
1 |
|
使用私钥解密文件:
1 |
|
注意:
- 填充方式可通过选项指定:
-pkeyopt rsa_padding_mode:oaep
签名与验证
签名(输入必须是哈希值,该命令不会对输入内容执行哈希操作)
1 |
|
验证
1 |
|
OpenSSH
注意,OpenSSH生成公钥私钥格式与OpenSSL不同!!不要混淆
它的私钥头部如下:
1 |
|
它生成私钥的命令
1 |
|
散列函数(Cryptographic hash Functions)
散列函数 又称 哈希函数、摘要算法。它是一种单向算法,用户可以通过散列函数对目标信息生成一段特定长度的唯一的Hash值,却不能通过这个Hash值逆向获得目标信息。
特点:不可逆,加密后值很小(128位,256位,512位等)。
散列函数有两大家族:
- MD:Message Digest Algorithm
- MD4:1990年发布。早已被攻破。
- MD5:Message Digest 5,1992年发布。早已被攻破,不适用于安全认证或数字签名。
- SHA:安全散列算法(Secure Hash Algorithm),由美国国家安全局(NSA)设计,美国国家标准与技术研究所发布。
- SHA-0:1993年发布后,但很快被撤回。
- SHA-1:1995年发布,使用很广泛(用于 TLS, GnuPG, SSH, IPsec等)。2017年已经被荷兰CWI和Google攻破。
- SHA-2:2001年发布,包括SHA-224, SHA-256, SHA-384, SHA-512, SHA512/224, SHA512/256。
- SHA-3:2015年发布。
算法列表
- https://www.openssl.org/docs/manmaster/man1/openssl-dgst.html
OpenSSL支持的算法列表,可以通过openssl dgst -list
命令获得:
1 2 3 4 5 6 7 8 9 10 11 |
|
也可以通过openssl list -digest-algorithms
命令(这个返回的列表比较长,多出来的别名?):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
生成摘要
要获得一个文件的md5值,可以使用dgst命令:
1 2 |
|
或者直接用md5命令
1 |
|
将结果以二进制输出到文件
1 |
|
使用16进制编辑器查看dgst.out结果
1 2 |
|
默认的dgst是SHA256:
1 2 |
|
加密后的值被称为hash值,hash值用于确保数据的完整性,但是不能保证数据传输存在身份认证机制。
数字签名
数字签名它是基于非对称密钥加密技术与数字摘要算法技术的应用,只有私钥拥有者才能产生别人无法伪造的一段数字串。
发送方通过私钥加密后数字签名发送给接收方,接收方使用公钥解密,通过对比解密后的摘要和使用Hash函数对数据电文进行计算的摘要 判定其是否被篡改。
生成签名
1 |
|
验证签名
1 2 |
|
结果为 Verification failure 或 Verified OK
OpenSSL 作为CA
配置文件
在Ubuntu下,配置文件在 /etc/ssl/openssh.cnf
在Windows下安装OpenSSL-Win32,安装目录下有一个配置文件openssh.cnf
如果报错,可通过环境变量来指定它。
set OPENSSL_CONF=[path-to-OpenSSL-install-dir]\openssl.cnf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
建立CA目录
1 2 3 4 5 6 |
|
- private/ 存放证书私钥
- serial 里面写入序列号,比如可以写入“8101”或其他数字,后期递增 echo 8101 > serial
CA自签名证书
生成私钥,并放入我们在配置文件中指定的位置
1 |
|
生成CA证书请求
1 |
|
签名证书,将其放置到配置文件期望的位置
1 |
|
在该步骤中,配置文件开始起作用了,当前目录结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
接下来,该CA就可以为其他csr生成证书了。
OpenSSL命令行参数备忘
- 非对称算法:-in -out 默认都是私钥,通过-pubout指定输出公钥;同样通过-pubin指定输入公钥。
-
通过s client可以读取网站的证书
$ openssl s_client -connect blog.debao.me:443
-
x509和pkcs12这两个命令可用于操作证书,比如证书格式之间的转换:
openssl pkcs12 -export -out certificate.pfx -inkey privatekey.key -in cert.crt
- 生成 证书请求文件 (回答它的提问,完成过程),而后用csr去找CA机构申请正式的证书。
openssl req -new -key x.key -out x.csr
Qt 与 OpenSSL
Qt官方提供的Windows下的安装包,默认不打包OpenSSL。在Qt5.13之前,如果需要QSslScocket功能,需要手动安装OpenSSL。安装时需要注意版本!!!
这块有点乱,先简单记录。要验证的话,可能需要结合Qt源码,以及Qt的bug来看才行
- Qt 从 5.2.0 起,不再官方支持 OpenSSL 低于 1.0.0 的版本。
- Qt 从 5.10起,官方二进制包开始使用OpenSSL 1.1
- Qt 从 5.12.4起,官方二进制包开始使用 OpenSSL1.1.1 的。
- Qt 从 6.2.0 起,开始支持 OpenSSL3.0(自己编译Qt)
- Qt 从 6.5.0 起,官方二进制包开始使用 OpenSSL 3.0。
简单说:
1 2 3 |
|
注: Qt 5.13起,在Windows下开始增加schannel作为ssl后端,可作为 openssl 的替代。Qt6.3起,编译Qt时,schannel插件已默认启用。如果不需要OpenSSL的扩展功能的话,新版本的Qt程序可以不用纠结OpenSSL的问题,使用Schannel就行。
其他
Git
Windows下安装的Git,会自带 openssl,这个东西功能不全,要避免使用。
钥yào yuè
密钥中的“钥”,读音争议很大 。
《现代汉语词典(第7版)》:【密钥】mìyuè (口语中多读mìyào)。
参考
- https://www.openssl.org/docs/man3.0/
- https://en.wikipedia.org/wiki/OpenSSL
- https://www.feistyduck.com/library/openssl-cookbook/online/
- https://blog.csdn.net/zhihao_li/article/details/131068038
- https://unix.stackexchange.com/questions/296697/how-to-encrypt-a-file-with-private-key