升级到 OpenSSL 3.x 后,很多老系统生成的证书无法验证通过,错误提示类似 error:0308010C:digital envelope routines。这通常是因为 OpenSSL 3.0 默认禁用了遗留算法(MD5、SHA-1、DES、RC4 等)。本文介绍如何配置 Legacy Provider 来处理这些遗留证书。
问题背景#
OpenSSL 3.0 引入了 Provider 架构,密码学算法的实现被分离到独立的 Provider 中:
- Default Provider:提供现代安全算法(AES、SHA-2、ChaCha20 等)
- FIPS Provider:提供 FIPS 140-2 认证的算法
- Legacy Provider:提供遗留算法(MD5、SHA-1、DES、RC4、CAST 等)
默认情况下,只有 Default Provider 启用,因此使用遗留算法的操作会失败。
验证问题现象#
1. DES 加密失败#
1
2
3
4
5
|
$ echo -n "test" | openssl enc -des-ede3-cbc
enc: Unknown cipher: des-ede3-cbc
error:0308010C:digital envelope routines:inner_evp_generic_fetch:unsupported:
../crypto/evp/evp_fetch.c:386:Global default library context, Algorithm (des-ede3-cbc : 27),
Properties (<null>)
|
2. MD5 摘要失败#
1
2
3
4
5
|
$ echo -n "test" | openssl dgst -md5
Error setting digest algorithm
00809DBE847F0000:error:13000084:HL routines:EVP_MD_fetch:unknown digest:
../crypto/evp/evp_fetch.c:386:Global default library context, Algorithm (MD5),
Properties (<null>)
|
3. SHA-1 签名证书验证#
创建测试证书(仅用于演示,生产环境勿用 SHA-1):
1
2
3
|
$ openssl req -x509 -newkey rsa:2048 \
-keyout /tmp/test-key.pem -out /tmp/test-cert.pem \
-days 365 -sha1 -nodes -subj "/CN=test.example.com"
|
查看证书签名算法:
1
2
|
$ openssl x509 -in /tmp/test-cert.pem -noout -text | grep "Signature Algorithm"
Signature Algorithm: sha1WithRSAEncryption
|
尝试验证自签名证书:
1
2
|
$ openssl verify -CAfile /tmp/test-cert.pem /tmp/test-cert.pem
/tmp/test-cert.pem: OK
|
注意:自签名证书验证通常不会失败,因为 OpenSSL 仍然支持 SHA-1 用于签名验证,但使用 SHA-1 签名的证书链验证可能失败。
4. 查看当前 Provider 状态#
1
2
3
4
5
6
|
$ openssl list -providers
Providers:
default
name: OpenSSL Default Provider
version: 3.0.20
status: active
|
可以看到只有 default Provider 处于 active 状态。
解决方案#
方法一:命令行临时启用 Legacy Provider#
对于单次操作,可以通过 -provider 和 -propquery 参数临时启用 Legacy Provider:
使用 MD5 摘要#
1
2
|
$ echo -n "test" | openssl dgst -md5 -provider legacy
MD5(stdin)= 098f6bcd4621d373cade4e832627b4f6
|
使用 DES 加密#
1
2
|
$ echo -n "test" | openssl enc -des-ede3-cbc -provider legacy -pbkdf2 -salt -pass pass:password | base64
Salted__9'test encrypted data...=
|
验证 SHA-1 签名证书#
1
2
|
$ openssl verify -CAfile /tmp/test-cert.pem -provider legacy /tmp/test-cert.pem
/tmp/test-cert.pem: OK
|
方法二:环境变量全局启用#
设置环境变量让所有 OpenSSL 操作默认使用 Legacy Provider:
1
2
3
4
5
|
# 方式1:设置 Provider 路径
export OPENSSL_MODULES=/usr/lib/x86_64-linux-gnu/ossl-modules
# 方式2:通过 openssl.cnf 配置
# 见下文"方法三"
|
方法三:配置文件全局启用#
编辑 OpenSSL 配置文件(通常是 /etc/ssl/openssl.cnf 或 ~/.openssl.cnf):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
openssl_conf = openssl_init
[openssl_init]
providers = provider_sect
[provider_sect]
default = default_sect
legacy = legacy_sect
[default_sect]
activate = 1
[legacy_sect]
activate = 1
module = /usr/lib/x86_64-linux-gnu/ossl-modules/legacy.so
|
配置完成后,验证 Provider 加载:
1
2
3
4
5
6
7
8
9
10
|
$ openssl list -providers
Providers:
default
name: OpenSSL Default Provider
version: 3.0.20
status: active
legacy
name: OpenSSL Legacy Provider
version: 3.0.20
status: active
|
现在 DES、MD5 等遗留算法可以正常使用:
1
2
3
4
5
|
$ echo -n "test" | openssl dgst -md5
MD5(stdin)= 098f6bcd4621d373cade4e832627b4f6
$ echo -n "test" | openssl enc -des-ede3-cbc -pbkdf2 -salt -pass pass:password | base64
U2FsdGVkX18+test encrypted output
|
方法四:针对特定算法使用 Property Query#
可以使用 -propquery 参数精确控制使用哪个 Provider:
1
2
3
4
5
|
# 强制使用 legacy provider 的 MD5
echo -n "test" | openssl dgst -md5 -propquery "provider=legacy"
# 优先使用 default provider,fallback 到 legacy
echo -n "test" | openssl dgst -md5 -propquery "provider=default,provider=legacy"
|
Legacy Provider 包含的算法#
Legacy Provider 提供以下遗留算法(请勿在生产环境使用):
摘要算法#
1
2
3
4
5
6
7
8
9
10
|
$ openssl list -digest-algorithms -provider legacy | grep -E "MD5|MD4|SHA1"
MD5
MD5-SHA1
MD4
RSA-MD4 => MD4
RSA-MD5 => MD5
sha1WithRSAEncryption => SHA1
SHA1
ssl3-md5 => MD5
ssl3-sha1 => SHA1
|
对称加密算法#
1
2
3
4
5
6
7
8
9
10
11
|
$ openssl list -cipher-algorithms -provider legacy | grep -E "DES|RC4|CAST"
DES-CBC
DES-CFB
DES-ECB
DES-EDE
DES-EDE-CBC
DES-EDE3-CBC
RC4
RC4-40
CAST5-CBC
...
|
签名算法#
1
2
3
4
5
6
|
$ openssl list -signature-algorithms -provider legacy | grep -E "MD5|SHA1"
ecdsa-with-SHA1
sha1WithRSAEncryption
md5WithRSAEncryption
md5WithRSA
...
|
安全警告#
⚠️ 重要提示:Legacy Provider 中的算法存在严重安全风险:
- MD5:存在碰撞攻击,已被弃用
- SHA-1:存在碰撞攻击,不推荐使用
- DES:密钥空间太小(56 位),可暴力破解
- RC4:存在多个安全漏洞,已被禁用
使用建议:
- 仅用于兼容旧系统
- 尽快迁移到现代安全算法
- 迁移完成后禁用 Legacy Provider
- 切勿在生产环境新增使用这些算法
完整配置示例#
以下是生产环境中处理遗留系统的推荐配置:
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
|
# /etc/ssl/openssl.cnf
openssl_conf = openssl_init
# 默认启用 default provider
[openssl_init]
providers = provider_sect
ssl_conf = ssl_sect
[provider_sect]
default = default_sect
# legacy 仅在需要时手动启用
legacy = legacy_sect
[default_sect]
activate = 1
[legacy_sect]
activate = 0 # 默认禁用,手动启用
module = /usr/lib/x86_64-linux-gnu/ossl-modules/legacy.so
[ssl_sect]
system_default = system_default_sect
[system_default_sect]
# 启用遗留协议兼容(可选)
# CipherString = DEFAULT:@SECLEVEL=1
|
启用 Legacy Provider:
1
2
3
4
|
# 临时启用
openssl genrsa -provider legacy 2048
# 或修改配置将 legacy 的 activate 改为 1
|
- 问题根源:OpenSSL 3.x 默认只启用 Default Provider,遗留算法不可用
- 临时方案:使用
-provider legacy 命令行参数
- 全局方案:在
openssl.cnf 中配置 Legacy Provider
- 安全建议:仅用于兼容旧系统,尽快升级到现代安全算法
参考来源