OpenSSL
OpenSSL 是 SSL 和 TLS 协议的开源实现,旨在尽可能灵活。它支持多种平台,包括 BSD、Linux、OpenVMS、Solaris 和 Windows。
安装
openssl 在 Arch Linux 上默认安装(作为 coreutils 的依赖)。
有多种 OpenSSL 库绑定可供开发者使用
- python-pyopenssl
- perl-net-ssleay
- lua-sec, lua52-sec, lua51-sec
- haskell-hsopenssl
- haskell-openssl-streams
配置
在 Arch Linux 上,OPENSSLDIR 是 /etc/ssl。
OpenSSL 配置文件通常放在 /etc/ssl/openssl.cnf,初看可能有些复杂。请记住,变量在赋值时可能会被展开,这与 shell 脚本的工作方式类似。有关配置文件格式的详细解释,请参阅 config(5ssl)。
req 部分
与生成密钥、请求和自签名证书相关的设置。
req 部分负责 DN 提示。一个普遍的误解是“通用名称”(CN) 提示,它暗示应该以用户的真实姓名作为值。终端用户证书需要以计算机主机名作为 CN,而 CA 则不应具有有效的 TLD,这样就不可能出现证书颁发机构 (CA) 证书中的 CN 与终端用户证书中的 CN 组合匹配,而被某些软件误解为终端用户证书是自签名的。一些 CA 证书甚至没有 CN,例如
$ openssl x509 -subject -noout -in /etc/ssl/certs/AC_RAIZ_FNMT-RCM.pem
subject=C=ES, O=FNMT-RCM, OU=AC RAIZ FNMT-RCM
用法
本节假设您已阅读 Transport Layer Security#获取证书。
生成 Ed25519 私钥
$ openssl genpkey -algorithm ed25519 -out filename
生成 Curve25519 私钥
$ openssl genpkey -algorithm x25519 -out filename
生成 ECDSA 私钥
$ openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out filename
生成 RSA 私钥
使用 openssl-genpkey(1ssl),该命令根据 openssl(1ssl) Supersedes genrsa。
$ openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:keysize -out filename
如果需要加密密钥,请使用 -aes-256-cbc 选项。
生成证书签名请求
$ openssl req -new -sha256 -key private_key -out filename
显示证书签名请求
证书签名请求以编码格式存储。要以人类可读的格式查看请求
$ openssl req -noout -text -in filename
生成自签名证书
$ openssl req -key private_key -x509 -new -days days -out filename
在一条命令中生成自签名证书及私钥
您可以将上述 OpenSSL 命令合并为一条,这在某些情况下可能很方便。
ECDSA
$ openssl req -x509 -newkey ec -pkeyopt 'ec_paramgen_curve:P-256' -days days -keyout key_filename -out cert_filename
RSA
$ openssl req -x509 -newkey rsa:4096 -days days -keyout key_filename -out cert_filename
使用 CA 证书签署证书签名请求
$ openssl x509 -req -in cert_req_filename -days days -CA CA_cert -CAkey CA_cert_private_key -CAserial CA_cert_serial_file -out cert_out
生成 Diffie–Hellman 参数
DH,Diffie–Hellman,密钥交换是一种协议,用于在双方之间协商共享密钥,而协商本身通过公共网络安全地进行。(维基百科文章)。生成的共享密钥可用于通过公共网络交换数据的秘密通信。DH 协议通过一种方式建立双方对最终共享密钥的贡献,即使有被动监听者也无法重建结果共享密钥。在公共网络上实现共享密钥的另一种常见方法是,一方使用长期非对称密钥加密该密钥并将其发送给密钥所有者(如 RSA 密钥交换中的情况)[1]。因此,其他算法随后用于加密本身[2]。为了设定协商过程中将提出的要求,双方可以预先定义一组要求。这些要求就是 Diffie–Hellman 参数。定义这些参数的常用方法是使用数学函数。常用的函数有两种:模素数的指数运算(形成有限域 Diffie-Hellman,或 FFDH)和椭圆曲线上的点乘(形成椭圆曲线 Diffie-Hellman,或 ECDH)。
当前的 最佳实践是使用 RFC:7919 中的标准 DH 组之一,例如 ffdhe2048。
或者,您可以生成一个自己的随机组
$ openssl dhparam -out filename 2048
-dsaparam 选项 [3]。显示证书信息
$ openssl x509 -text -in cert_filename
要查看服务器的证书,请使用 openssl-s_client(1ssl)
$ openssl s_client -showcerts -connect hostname:port </dev/null | openssl x509 -text
显示证书指纹
$ openssl x509 -noout -in cert_filename -fingerprint -digest
-digest 是可选的,可以是 -md5、-sha1、-sha256 或 -sha512 之一。请参阅 x509(1ssl) § 输入、输出和通用选项 中关于未指定摘要的情况。
转换证书格式
使用 openssl x509 将证书从二进制 (DER) 格式转换为 PEM 格式(带有 BEGIN CERTIFICATE 标头的文本格式):
$ openssl x509 -inform DER -in myCA.crt -out myCA_pem.crt
使用第三方提供者
OpenSSL 3 引入了提供者 (providers) 的新概念,用于 OpenSSL 的插件化。可以在不重新编译 OpenSSL 的情况下使用 OpenSSL 未包含的算法。
oqsprovider
要测试 NIST 后量子密码学算法,可以安装 Open Quantum Safe 提供者 oqsproviderAUR。例如,您可以使用 ML-DSA(以前称为 CRYSTALS-Dilithium)的某个变体来生成一个抗量子的自签名证书及私钥 ML-DSA。
$ openssl req -provider default -provider oqsprovider -x509 -newkey mldsa65 -days days -keyout key -out cert
tpm2-openssl
要将 ECDSA 和 RSA 私钥存储在 TPM 中,请安装 tpm2-openssl。有关如何使用它的文档,请参阅其 README。
故障排除
解密时出现 "bad decrypt"
OpenSSL 1.1.0 将 dgst 和 enc 命令的默认摘要算法从 MD5 更改为 SHA256。[4]
因此,如果一个文件是用 OpenSSL 1.0.2 或更早版本加密的,尝试用最新版本解密可能会出现类似如下的错误:
error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:crypto/evp/evp_enc.c:540
提供 -md md5 选项应能解决问题
$ openssl enc -d -md md5 -in encrypted -out decrypted
Python 3.10 和 "ca md too weak" 错误
在 Python 3.10 中,默认情况下有一个硬编码的允许 OpenSSL 加密算法列表。一些不太安全的算法(如 MD5)已在 ssl 模块级别被禁用,忽略了 OpenSSL 的系统范围配置。这有时会导致旧证书出现奇怪的错误,甚至在建立 https 连接时,例如:
requests.exceptions.SSLError: HTTPSConnectionPool(host='a.kind.of.example.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLError(398, '[SSL: CA_MD_TOO_WEAK] ca md too weak (_ssl.c:3862)')))
要使 Python 遵循系统配置,您可能需要重新编译它,并在 ./configure 中添加 --with-ssl-default-suites=openssl 参数。此问题也已报告为 FS#73549。
设置加密算法 XXX 出错
如果您尝试使用一个“已弃用”的加密算法,您将收到此类错误:
$ openssl bf -d -in cipher_file -K passphrase Error setting cipher BF-CBC 4087A97A8A7F0000:error:0308010C:digital envelope routines:inner_evp_generic_fetch:unsupported:crypto/evp/evp_fetch.c:341:Global default library context, Algorithm (BF-CBC : 12)
自 OpenSSL 3.0 起,加密算法通过“提供者”提供。最旧或最少使用的算法属于 legacy 提供者。[5]
如果您需要使用已弃用的算法,如 DES、RC4、Blowfish 等,您必须在命令行中添加 -provider legacy 选项。
这是一个用于解密 Blowfish 密码的完整示例。
$ openssl bf -d -in cipher_file -provider legacy -provider default -K passphrase
参见
- OpenSSL 维基百科页面,包含背景信息。
- OpenSSL 的 wiki 旨在收集、组织和完善当前分散在多个位置和格式的有关 OpenSSL 的有用信息。
- FreeBSD 手册
- 创建已签名的 SSL 证书的分步指南
- OpenSSL 证书颁发机构:一个演示如何充当您自己的证书颁发机构的指南。
- Ivan Ristić 的《Bulletproof SSL and TLS》,对 SSL/TLS 的更正式的介绍