OpenSSL

密码学和 SSL/TLS 工具包

migration_guide

NAME

migration_guide - OpenSSL 迁移指南

SYNOPSIS

有关详细信息,请参阅各个手册页。

DESCRIPTION

本指南详细介绍了迁移到新版本 OpenSSL 所需的更改。目前这涵盖了 OpenSSL 3.0。对于早期版本,请参阅https://github.com/openssl/openssl/blob/master/CHANGES.md。有关 OpenSSL 3.0 中引入的一些关键概念的概述,请参阅crypto(7)

OPENSSL 3.0

相对于 OpenSSL 1.1.1 的主要变化

主要版本

OpenSSL 3.0 是一个主要版本,因此当前使用旧版本 OpenSSL 的任何应用程序至少需要重新编译才能使用新版本。我们的目的是,如果大多数应用程序以前使用 OpenSSL 1.1.1,那么它们将在 OpenSSL 3.0 上保持不变。但是,这并不能保证,在某些情况下可能需要进行一些更改。如果应用程序需要利用 OpenSSL 3.0 中提供的某些新功能(例如 FIPS 模块的可用性),也可能需要进行更改。

许可证变更

在以前的版本中,OpenSSL 是根据OpenSSL 和 SSLeay 双许可证(两个许可证均适用)获得许可的。从 OpenSSL 3.0 开始,它被Apache License v2取代。

提供商和 FIPS 支持

OpenSSL 1.1.1 的主要变化之一是引入了 Provider 概念。提供者聚集在一起并提供可用的算法实现。使用 OpenSSL 3.0,可以通过编程方式或通过配置文件指定您想要为任何给定应用程序使用哪些提供程序。OpenSSL 3.0 附带 5 个不同的提供商作为标准。随着时间的推移,第三方可能会分发可插入 OpenSSL 的其他提供程序。通过提供者提供的所有算法实现都可以通过“高级”API 访问(例如那些前缀为 的函数EVP)。无法使用“低级 API”访问它们。

FIPS 提供程序是可用的标准提供程序之一。这使得 FIPS 验证的加密算法可用。FIPS 提供程序默认处于禁用状态,需要在配置时使用该enable-fips选项显式启用。如果启用,除了其他标准提供程序之外,还会构建并安装 FIPS 提供程序。无需单独的安装过程。然而,有一个专用的install_fipsmake 目标,它用于仅将 FIPS 提供程序安装到现有 OpenSSL 安装中的特殊目的。

并非所有算法在特定时刻都可用于应用程序。如果应用程序代码通过 EVP 接口使用任何摘要或密码算法,则应用程序应验证EVP_EncryptInit(3)EVP_EncryptInit_ex(3)EVP_DigestInit(3)函数的结果。如果请求的算法不可用,这些功能将失败。

有关遗留提供商的信息, 另请参阅“遗留算法” 。

另请参阅“完成 FIPS 模块的安装”“在应用程序中使用 FIPS 模块”

低级 API

OpenSSL 历史上提供了两套用于调用加密算法的 API:“高级”API(例如 API EVP)和“低级”API。高级 API 通常设计为适用于所有算法类型。“低级”API 针对特定算法实现。例如,EVP API 提供函数EVP_EncryptInit_ex(3)EVP_EncryptUpdate(3)EVP_EncryptFinal(3)来执行对称加密。这些函数可以与 AES、CHACHA、3DES 等算法一起使用。另一方面,要使用低级 API 进行 AES 加密,您必须调用 AES 特定函数,例如 AES_set_encrypt_key(3) 、 AES_encrypt ( 3 )和很快。3DES 的功能有所不同。长期以来,OpenSSL 开发团队一直非正式地不鼓励使用低级 API。然而在 OpenSSL 3.0 中,这变得更加正式。所有此类低级 API 均已被弃用。您仍然可以在应用程序中使用它们,但您可能会在编译期间开始看到弃用警告(取决于编译器对此的支持)。已弃用的 API 可能会从 OpenSSL 的未来版本中删除,因此强烈建议您更新代码以使用高级 API。

“低级函数的弃用” 中有更详细的描述

遗留算法

一些通过 EVP API 提供的 加密算法(例如MD2DES)现在被视为遗留算法,强烈建议不要使用它们。这些旧版 EVP 算法在 OpenSSL 3.0 中仍然可用,但默认情况下不可用。如果您想使用它们,则必须加载旧提供程序。这可以像更改配置文件一样简单,也可以通过编程方式完成。有关算法的完整列表,请参阅OSSL_PROVIDER-legacy(7) 。使用 EVP API 访问这些算法的应用程序应该使用更现代的算法。如果这是不可能的,那么这些应用程序应该确保旧提供程序已被加载。这可以通过编程或配置来实现。有关提供程序的更多信息, 请参阅crypto(7)手册页。

引擎和“METHOD”API

支持提供程序的重构与用于支持引擎的 API 发生内部冲突,包括 ENGINE API 和任何创建或修改自定义“方法”的函数(例如 EVP_MD_meth_new(3) 、 EVP_CIPHER_meth_new(3) 、EVP_PKEY_meth_new ( 3 ) RSA_meth_new ( 3)EC_KEY_METHOD_new(3)等)。这些函数在 OpenSSL 3.0 中已被弃用,这些 API 的用户应该知道它们的使用可能会绕过提供程序的选择和配置,从而产生意想不到的后果。这对于使用 OpenSSL 3.0 FIPS 模块编写的应用程序尤其重要,如下所述。强烈鼓励外部引擎的作者和维护者使用新的 Provider API 重构其代码,将引擎转换为提供者,并避免弃用的方法。

支持旧版引擎

如果 openssl 不是在没有引擎支持或已弃用的 API 支持的情况下构建的,引擎仍然可以工作。然而,它们的适用性将受到限制。

通过引擎提供的新算法仍然有效。

引擎支持的密钥可以通过自定义OSSL_STORE实现 加载。在这种情况下,通过ENGINE_load_private_key(3)创建的EVP_PKEY对象将被视为遗留对象并将继续工作。

为了确保未来的兼容性,引擎应该转向提供商。要首选基于提供商的硬件卸载,您可以指定默认属性以首选您的提供商。

版本控制方案

OpenSSL 版本控制方案已随 OpenSSL 3.0 版本而更改。新的版本控制方案具有以下格式:

主要.次要.补丁

对于 OpenSSL 1.1.1 及更低版本,不同的补丁级别由发行版本号末尾的字母表示。这将不再使用,而是由版本中的最终数字指示补丁级别。第二个(次要)数字的变化表示可能已添加新功能。具有相同主编号的 OpenSSL 版本与 API 和 ABI 兼容。如果主版本号发生变化,则无法保证 API 和 ABI 兼容性。

有关更多信息,请参阅OpenSSL_version(3)

其他主要新功能
证书管理协议(CMP、RFC 4210)

这还涵盖 CRMF (RFC 4211) 和 HTTP 传输 (RFC 6712) 请参阅openssl-cmp(1)OSSL_CMP_exec_certreq(3)作为起点。

HTTP(S) 客户端

正确的 HTTP(S) 客户端,支持 GET 和 POST、重定向、纯文本和 ASN.1 编码内容、代理和超时。

密钥导出函数 API (EVP_KDF)

这简化了添加新 KDF 和 PRF 实现的过程。

以前,KDF 算法被迫使用 EVP_PKEY 对象,这不是逻辑映射。使用使用 EVP_PKEY(scrypt、TLS1 PRF 和 HKDF)的 KDF 算法的现有应用程序可能会较慢,因为它们在内部使用 EVP_KDF 桥接器。所有新应用程序都应使用新的EVP_KDF(3)接口。另请参阅OSSL_PROVIDER-default(7) 中的“密钥派生函数 (KDF)”OSSL_PROVIDER-FIPS(7) 中的“密钥派生函数 (KDF)”

消息验证码API (EVP_MAC)

这简化了添加 MAC 实现的过程。

这包括通用 EVP_PKEY 到 EVP_MAC 桥接器,以方便通过EVP_DigestSign(3)EVP_DigestVerify(3) 等功能中的原始私钥继续使用 MAC 。

所有新应用程序都应使用新的EVP_MAC(3)接口。另请参阅OSSL_PROVIDER-default(7) 中的“消息身份验证代码 (MAC)”OSSL_PROVIDER-FIPS(7) 中的“消息身份验证代码 (MAC)”

算法获取

使用提供程序时,调用 EVP_sha256() 和 EVP_aes_256_gcm() 等便捷函数可能会导致性能损失。从提供者检索算法涉及按名称搜索算法。这比直接访问方法表要慢得多。如果多次使用某个算法,建议预取算法。请参阅crypto(7) 中的“性能”crypto(7) 中的“显式获取”crypto(7) 中的“隐式获取”

支持 Linux 内核 TLS

为了使用 KTLS,必须使用enable-ktls配置选项编译对其的支持。它还必须在运行时使用SSL_OP_ENABLE_KTLS选项启用。

新算法
  • KDF 算法“SINGLE STEP”和“SSH”

    请参见EVP_KDF-SS(7)EVP_KDF-SSHKDF(7)

  • MAC 算法“GMAC”和“KMAC”

    请参见EVP_MAC-GMAC(7)EVP_MAC-KMAC(7)

  • KEM 算法“RSASVE”

    请参阅EVP_KEM-RSA(7)

  • 密码算法“AES-SIV”

    请参阅EVP_EncryptInit(3) 中的“SIV 模式”

  • EVP 层支持 AES Key Wrap 逆密码。

    逆密码使用 AES 解密进行包装,使用 AES 加密进行解包。算法为:“AES-128-WRAP-INV”、“AES-192-WRAP-INV”、“AES-256-WRAP-INV”、“AES-128-WRAP-PAD-INV”、“AES-192” -WRAP-PAD-INV”和“AES-256-WRAP-PAD-INV”。

  • CTS 密码添加到 EVP 层。

    算法为“AES-128-CBC-CTS”、“AES-192-CBC-CTS”、“AES-256-CBC-CTS”、“CAMELLIA-128-CBC-CTS”、“CAMELLIA-192-CBC- CTS”和“CAMELLIA-256-CBC-CTS”。支持 CS1、CS2 和 CS3 变体。

CMS 和 PKCS#7 更新
  • 添加了 CAdES-BES 签名验证支持。

  • 向 CMS API 添加了 CAdES-BES 签名方案和属性支持 (RFC 5126)。

  • 使用 AES_GCM 添加了 AuthEnvelopedData 内容类型结构 (RFC 5083)

    这使用加密消息语法的 AES-GCM 参数 (RFC 5084)。其目的是支持使用 AES GCM 模式进行身份验证和加密的数字信封的加密和解密。

  • PKCS7_get_octet_string(3)PKCS7_type_is_other(3)已公开。

PKCS#12 API 更新

使用 PKCS12_create() 函数创建 pkcs12 的默认算法已更改为更现代的基于 PBKDF2 和 AES 的算法。默认 MAC 迭代计数已更改为 PKCS12_DEFAULT_ITER,以使其与基于密码的加密迭代计数相等。MAC 计算的默认摘要算法已更改为 SHA-256。pkcs12 应用程序现在支持 -legacy 选项,该选项可恢复以前的默认算法以支持与遗留系统的互操作性。

添加了增强的 PKCS#12 API,它接受库上下文OSSL_LIB_CTX和(如果相关)属性查询。处理 PKCS#7 和 PKCS#8 对象的其他 API 也根据需要得到了增强。这包括:

PKCS12_add_key_ex(3)PKCS12_add_safe_ex(3)PKCS12_add_safes_ex(3) 、 PKCS12_create_ex(3)PKCS12_decrypt_skey_ex(3) PKCS12_init_ex ( 3 )、 PKCS12_item_decrypt_d2i_ex(3) 、 PKCS12 _item_i2d_encrypt_ex(3)PKCS12_key_gen_asc_ex(3)、PKCS12_key_gen_uni_ex (3)PKCS12_key_gen_utf8_ex(3)PKCS12_pack_p7encda​​ta_ex(3)PKCS12_pbe_crypt_ex(3) 、 PKCS12_PBE_keyivgen_ex(3 ) 、PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(3 )PKCS5_pbe2_set_iv_ex(3) 、 PKCS5_pbe_set0_algor_ex(3)、PKCS5_pbe_set_ex (3)、PKCS5_pbkdf2_set_ex (3)PKCS5_v2_PBE_keyivgen_ex(3)PKCS5_v2_scrypt_keyivgen_ex(3)PKCS8_decrypt_ex(3)PKCS8_encrypt_ex(3)PKCS8_set0_pbe_ex(3)

作为此更改的一部分,EVP_PBE_xxx API 还可以接受库上下文和属性查询,并将调用支持这些参数的密钥/IV 派生函数的扩展版本。这包括EVP_PBE_CipherInit_ex(3)EVP_PBE_find_ex(3)EVP_PBE_scrypt_ex(3)

PKCS#12 KDF 与 FIPS

与 1.xy 不同,当使用不与 FIPS 提供程序一起使用的 MAC 创建 PKCS#12 结构时使用的 PKCS12KDF 算法,因为 PKCS12KDF 不是 FIPS 可批准的机制。

请参阅EVP_KDF-PKCS12KDF(7)PKCS12_create(3)openssl-pkcs12(1)OSSL_PROVIDER-FIPS(7)

Windows 线程同步变化

当操作系统支持时,Windows 线程同步使用读/写原语 (SRWLock),否则继续使用 CriticalSection。

追踪API

添加了新的通用跟踪 API,它支持通过跟踪输出启用检测。此功能主要是为了帮助开发人员,默认情况下处于禁用状态。要使用它,需要使用该enable-trace选项配置 OpenSSL。

如果启用了跟踪 API,应用程序可以通过将 BIO 注册为多个跟踪和调试类别的跟踪通道来激活跟踪输出。请参阅OSSL_trace_enabled(3)

关键验证更新

EVP_PKEY_public_check(3)EVP_PKEY_param_check(3)现在适用于更多密钥类型。这包括 RSA、DSA、ED25519、X25519、ED448 和 X448。以前(在 1.1.1 中)它们会返回 -2。对于没有参数的密钥类型,EVP_PKEY_param_check(3)将始终返回 1。

其他值得注意的弃用和更改
OpenSSL 错误代码的功能代码部分不再相关

该代码现在始终设置为零。相关函数已弃用。

STACK 和 HASH 宏已被清理

类型安全包装器在各处声明并实现一次。请参见DEFINE_STACK_OF(3)DECLARE_LHASH_OF(3)

RAND_DRBG 子系统已被删除

新的EVP_RAND(3)是部分替代:缺少 DRBG 回调框架。RAND_DRBG API 不太适合 EVP_RAND 和 EVP_RAND_CTX 实现的新提供商概念。

删除了 FIPS_mode() 和 FIPS_mode_set()

这些功能是旧版 API,不适用于新的提供商模型。应用程序应改用EVP_default_properties_is_fips_enabled(3)EVP_default_properties_enable_fips(3)

密钥生成速度较慢

Miller-Rabin 测试现在使用 64 轮,用于所有素数生成,包括 RSA 密钥生成。这会影响较大密钥大小的时间。

常规 2 素数 RSA 密钥的默认密钥生成方法已更改为 FIPS186-4 B.3.6 方法(基于辅助概率素数的条件生成概率素数)。此方法比原始方法慢。

更改 PBKDF2 以符合 SP800-132 而不是旧的 PKCS5 RFC2898

这会检查盐长度是否至少为 128 位,派生密钥长度至少为 112 位,并且迭代计数至少为 1000。为了向后兼容,默认情况下在默认提供程序中禁用这些检查,但可以通过FIPS 提供商中的默认设置。

要启用或禁用检查,请参阅EVP_KDF-PBKDF2(7)中的OSSL_KDF_PARAM_PKCS5可以使用EVP_KDF_derive(3)设置该参数。

强制执行 512 位的最小 DH 模数大小

较小的尺寸现在会导致错误。

SM2 按键变化

具有 SM2 曲线的 EC EVP_PKEY 已重新设计,自动变为 EVP_PKEY_SM2 而不是 EVP_PKEY_EC。

与以前的 OpenSSL 版本不同,这意味着应用程序无法调用EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)来获取 SM2 计算。

参数和密钥生成也经过重新设计,以便可以生成 EVP_PKEY_SM2 参数和密钥。应用程序现在必须直接生成 SM2 密钥,并且不能先创建 EVP_PKEY_EC 密钥。无法再导入具有除 SM2 椭圆曲线参数之外的域参数的 SM2 密钥。

SM2 密钥的验证已与常规 EC 密钥的验证分开,从而可以改进 SM2 验证过程,以拒绝加载不符合 SM2 ISO 标准的私钥。特别是,超出范围1 <= k < n-1 的私有标量k现在会被正确拒绝。

EVP_PKEY_set_alias_type() 方法已被删除

该函数使EVP_PKEY对象在设置后可变。在 OpenSSL 3.0 中,决定提供的密钥不应该能够更改其类型,因此此功能已被删除。

返回内部键的函数应被视为只读

EVP_PKEY_get0_RSA(3) 等函数在 OpenSSL 3.0 中的行为略有不同。之前他们返回了一个指向 libcrypto 内部使用的低级密钥的指针。从 OpenSSL 3.0 开始,此密钥现在可以保存在提供商中。调用这些函数只会返回内部密钥的句柄,其中首先使用此密钥构造 EVP_PKEY,例如使用诸如 EVP_PKEY_assign_RSA(3) 、 EVP_PKEY_set1_RSA(3) 等函数。提供者管理的密钥,那么这些函数现在返回该密钥的缓存副本。第一次访问缓存密钥后对内部提供程序密钥发生的更改将不会反映在缓存副本中。同样,应用程序代码对缓存副本所做的任何更改都不会反映在内部提供程序密钥中。

由于上述原因,从这些函数返回的键通常应被视为只读。为了强调这一点,从EVP_PKEY_get0_RSA(3)EVP_PKEY_get0_DSA(3)EVP_PKEY_get0_EC_KEY(3)EVP_PKEY_get0_DH(3)返回的值已设为常量。这可能会破坏一些现有的代码。应修改因此更改而损坏的应用程序。首选解决方案是重构代码以避免使用这些已弃用的函数。如果失败,则应修改代码以使用 const 指针。EVP_PKEY_get1_RSA (3)EVP_PKEY_get1_DSA(3)EVP_PKEY_get1_EC_KEY(3)EVP_PKEY_get1_DH(3)函数继续返回非常量指针以使它们能够被“释放”。然而,它们也应该被视为只读。

公钥检查已从 EVP_PKEY_derive() 移至 EVP_PKEY_derive_set_peer()

这可能意味着在EVP_PKEY_derive_set_peer(3)中而不是在EVP_PKEY_derive(3)期间 导致错误。要禁用此检查,请使用 EVP_PKEY_derive_set_peer_ex(dh, peer, 0)。

打印格式对某些功能进行了外观更改

许多“打印”函数(例如X509_signature_print(3)X509_print_ex(3)X509_CRL_print_ex(3)和其他类似函数)的输出已被修改,因此 1.1.1 和 3.0 中观察到的输出之间可能存在外观差异。这也适用于openssl x509openssl crl应用程序的-text输出。

openssl程序 中的交互模式已被删除

从现在开始,不带参数运行它相当于openssl help

某些控制调用 (ctrl) 的错误返回值已更改

一项重大更改是,过去对于无效输入返回 -2 的控件现在返回 -1 表示一般错误情况。

DH 和 DHX 密钥类型具有不同的可设置参数

以前(在 1.1.1 中)这些冲突的参数是允许的,但现在会导致错误。有关详细信息,请参阅EVP_PKEY-DH(7) 。这会影响openssl-genpkey(1)生成 DH 参数 的行为。

EVP_CIPHER_CTX_set_flags() 顺序更改

如果使用来自提供者的密码,则只能在将密码分配给密码上下文之后设置EVP_CIPH_FLAG_LENGTH_BITS标志。有关详细信息, 请参阅EVP_EncryptInit(3) 中的“FLAGS” 。

操作上下文参数的验证

由于将加密操作的实现移至提供者,各种操作参数的验证可以被推迟,直到执行实际操作,而之前在设置操作参数时立即发生该操作。

例如,当使用 EVP_PKEY_CTX_set_ec_paramgen_curve_nid() 设置不受支持的曲线时,此函数调用不会失败,但随后使用 EVP_PKEY_CTX 的注册机操作将会失败。

从错误代码中删除功能代码

错误代码的功能代码部分现在始终设置为 0。因此,删除了 ERR_GET_FUNC() 宏。应用程序必须仅使用库编号和原因代码来解析错误代码。

ChaCha20-Poly1305 密码不允许使用截断的 IV 长度

在 OpenSSL 3.0 中,将 IV 长度设置为 12 以外的任何值都会导致错误。在 OpenSSL 3.0 之前,使用 EVP_CIPHER_CTX_ctrl(ctx, EVP_CRTL_AEAD_SET_IVLEN, ivlen, NULL),ivlen 可能小于所需的 12 字节长度。这导致 IV 具有前导零填充。

安装编译

请参阅发行版顶部的 INSTALL.md 文件,了解如何构建和安装 OpenSSL 3.0 的说明。另请参阅针对您的特定平台的各种特定于平台的NOTES 文件。

从 OpenSSL 1.1.1 升级

在大多数情况下,从 OpenSSL 1.1.1 升级到 OpenSSL 3.0 应该相对简单。您最有可能遇到问题的地方是您在代码中使用了低级 API(如上所述)。在这种情况下,您在编译应用程序时可能会开始看到弃用警告。如果发生这种情况,您有 3 个选择:

  1. 忽略警告。它们只是警告。已弃用的函数仍然存在,您仍然可以使用它们。但请注意,它们可能会从 OpenSSL 的未来版本中删除。

  2. 抑制警告。有关如何执行此操作的信息,请参阅编译器文档。

  3. 删除对低级 API 的使用。在这种情况下,您需要重写代码以使用高级 API

错误代码更改

由于 OpenSSL 3.0 提供了一种全新的编码器/解码器机制来处理广泛使用的文件格式,因此检查密钥加载失败的特定错误原因代码的应用程序代码可能需要更新。

受密码保护的密钥可能值得特别注意。如果仅将某些错误视为应再次询问用户密码的指示,则值得测试这些场景并处理新的相关代码。

可能有更多情况需要特殊处理,具体取决于调用应用程序代码。

从 OpenSSL 1.0.2 升级

从 OpenSSL 1.0.2 升级到 OpenSSL 3.0 可能会更加困难。除了上面“从 OpenSSL 1.1.1 升级”一节中讨论的问题外,还需要注意的主要事项是:

  1. 构建和安装过程发生了显着变化。

    检查安装顶部的 INSTALL.md 文件,了解如何为您的平台构建和安装 OpenSSL 的说明。另请阅读同一目录中适用于您的平台的各种 NOTES 文件。

  2. OpenSSL 3.0 中许多结构都变得不透明。

    结构定义已从公共头文件中删除并移至内部头文件。实际上,这意味着您不能再对某些结构进行堆栈分配。相反,它们必须通过某些函数调用进行堆分配(通常这些函数名称带有_new后缀)。此外,您必须使用“setter”或“getter”函数来访问这些结构中的字段。

    例如,以前的代码如下所示:

     EVP_MD_CTX md_ctx;
    
    /* This line will now generate compiler errors */
    EVP_MD_CTX_init(&md_ctx);

    代码需要修改为如下所示:

     EVP_MD_CTX *md_ctx;
    
    md_ctx = EVP_MD_CTX_new();
    ...
    ...
    EVP_MD_CTX_free(md_ctx);
  3. 添加了对 TLSv1.3 的支持。

    这对 SSL/TLS 应用程序有许多影响。有关更多详细信息, 请参阅TLS1.3 页面。

有关 OpenSSL 版本 1.0.2 和 1.1.0 之间的重大更改的更多详细信息,请参阅OpenSSL 1.1.0 更改页面

从 OpenSSL 2.0 FIPS 对象模块升级

OpenSSL 2.0 FIPS 对象模块是单独下载的,必须单独构建,然后集成到主 OpenSSL 1.0.2 构建中。在 OpenSSL 3.0 中,FIPS 支持完全集成到 OpenSSL 的主线版本中,不再需要单独下载。有关详细信息,请参阅“完成 FIPS 模块的安装”

函数调用 FIPS_mode() 和 FIPS_mode_set() 已从 OpenSSL 3.0 中删除。您应该重写您的应用程序以不使用它们。有关详细信息,请参阅fips_module(7)OSSL_PROVIDER-FIPS(7)

完成 FIPS 模块的安装

如果已配置 FIPS 支持,则将自动构建并安装 FIPS 模块。当前文档可以在README-FIPS文件中找到。

编程

为与 OpenSSL 1.1.1 配合使用而编写的应用程序大多只能与 OpenSSL 3.0 配合使用。但是,如果您想利用 OpenSSL 3.0 提供的一些新功能,则需要进行更改。为此,您需要了解 OpenSSL 3.0 中引入的一些新概念。阅读crypto(7) 中的“库上下文”以获取更多信息。

图书馆背景

库上下文允许复杂应用程序的不同组件各自使用不同的库上下文,并让不同的提供程序加载不同的配置设置。有关更多信息, 请参阅crypto(7) 中的“库上下文” 。

如果用户通过OSSL_LIB_CTX_new(3)创建OSSL_LIB_CTX,则可能需要更改许多函数以传递附加参数来处理库上下文。

使用库上下文 - 应该更改的旧函数

如果需要库上下文,则所有返回const EVP_MD * 的EVP_* 摘要函数(例如 EVP_sha256() )应替换为对EVP_MD_fetch(3)的调用。请参阅crypto(7) 中的“算法获取”

如果需要库上下文,则应通过调用EVP_CIPHER_fetch(3)来替换所有返回const EVP_CIPHER * 的EVP_* 密码函数(例如 EVP_aes_128_cbc() )。请参阅crypto(7) 中的“算法获取”

某些函数可以传递已使用库上下文设置的对象,例如d2i_X509(3)d2i_X509_CRL(3)d2i_X509_REQ(3)d2i_X509_PUBKEY(3)。如果传递 NULL,则创建的对象将使用默认库上下文进行设置。如果需要库上下文, 请使用X509_new_ex(3)X509_CRL_new_ex(3 ) 、X509_REQ_new_ex(3)X509_PUBKEY_new_ex(3) 。

下面列出的所有带有NAME 的函数都有一个替换函数NAME_ex,该函数将OSSL_LIB_CTX作为附加参数。具有其他映射的函数与相应的名称一起列出。

使用库上下文的新函数

如果需要,可以向以下函数传递库上下文。传递 NULL 将使用默认的库上下文。

供应商

提供者在 crypto(7) 中的“提供者” 中有详细描述。另请参阅crypto(7) 中的“OPENSSL PROVIDERS”

获取算法和属性查询

隐式和显式获取在 crypto(7) 中的“算法获取” 中有详细描述。

将 EVP 控件和标志映射到提供者OSSL_PARAM(3)参数

现有的控件函数(例如EVP_CIPHER_CTX_ctrl(3))和操作标志(例如EVP_MD_CTX_set_flags(3))在内部使用OSSL_PARAMS将信息传递给提供者对象或从提供者对象传递信息。有关参数的更多信息, 请参见OSSL_PARAM(3) 。

对于密码,请参阅EVP_EncryptInit(3) 中的“CONTROLS”EVP_EncryptInit(3) 中的“FLAGS”EVP_EncryptInit(3) 中的“PARAMETERS”

对于摘要,请参阅EVP_DigestInit(3) 中的“CONTROLS”EVP_DigestInit(3) 中的“FLAGS”EVP_DigestInit(3) 中的“PARAMETERS”

弃用低级函数

OpenSSL 3.0 中已弃用大量 API。本节介绍一些常见的弃用类别。有关引用这些类别的已弃用函数的列表, 请参阅“已弃用函数映射” 。

提供程序是引擎和低级方法重写的替代品

不推荐使用任何使用 ENGINE 的访问器(例如 EVP_PKEY_set1_engine())。使用引擎的应用程序应该使用提供程序。

在添加提供程序之前,通过更改算法使用的方法来覆盖算法。所有这些方法(例如 RSA_new_method() 和 RSA_meth_new() )现已弃用,可以通过使用提供程序来替换。

已弃用低级密钥类型的 i2d 和 d2i 函数

任何采用低级密钥类型的 i2d 和 d2i 函数(例如 d2i_DHparams())已被弃用。应用程序应使用OSSL_DECODER(3)OSSL_ENCODER(3) API 来读取和写入文件。有关更多详细信息,请参阅d2i_RSAPrivateKey(3) 中的“迁移”

已弃用的低级关键对象 getter 和 setter

设置或获取低级密钥对象(例如 EVP_PKEY_set1_DH() 或 EVP_PKEY_get0())的应用程序应使用 OSSL_ENCODER(请参阅OSSL_ENCODER_to_bio(3))或 OSSL_DECODER(请参阅OSSL_DECODER_from_bio(3))API,或者使用EVP_PKEY_fromdata(3 )EVP_PKEY_todata(3)

已弃用的低级关键参数 getter

直接访问低级对象的函数(例如RSA_get0_n(3))现已弃用。应用程序应使用EVP_PKEY_get_bn_param(3)EVP_PKEY_get_int_param(3)、 l<EVP_PKEY_get_size_t_param(3)>、EVP_PKEY_get_utf8_string_param(3)EVP_PKEY_get_octet_string_param(3)EVP_PKEY_get_params(3) 之一来访问 EVP_PKEY 中的字段。可获取的参数列于EVP_PKEY-RSA(7) 中的“通用 RSA 参数”EVP_PKEY-DH(7) 中的“DH 参数”EVP_PKEY-DSA(7) 中的“DSA 参数”EVP_PKEY-FFC 中的“FFC 参数”中(7)EVP_PKEY-EC(7) 中的“通用 EC 参数”EVP_PKEY-X25519(7) 中的“通用 X25519、X448、ED25519 和 ED448 参数”。应用程序还可以使用EVP_PKEY_todata(3)返回所有字段。

已弃用的低级关键参数设置器

直接访问低级对象的函数(例如RSA_set0_crt_params(3))现已弃用。应用程序应使用EVP_PKEY_fromdata(3)从用户提供的密钥数据创建新密钥。密钥一旦创建就应该是不可变的,因此如果需要,用户可以使用EVP_PKEY_todata(3)OSSL_PARAM_merge(3)EVP_PKEY_fromdata(3)来创建修改后的密钥。有关详细信息,请参阅EVP_PKEY-DH(7) 中的“示例” 。有关使用参数生成密钥的信息, 请参阅“已弃用的低级密钥生成函数” 。

已弃用的低级对象创建

低级对象是使用RSA_new(3)RSA_up_ref(3)RSA_free(3)等方法创建的。应用程序应使用高级 EVP_PKEY API,例如 EVP_PKEY_new(3)EVP_PKEY_up_ref(3)EVP_PKEY_free(3)。另请参见EVP_PKEY_CTX_new_from_name(3)EVP_PKEY_CTX_new_from_pkey(3)

EVP_PKEY 可以通过多种方式创建:另请参见“已弃用的低级密钥生成函数”“已弃用的低级密钥读写函数”“已弃用的低级密钥参数设置器”

已弃用的低级加密函数

长期以来,非正式地不鼓励使用AES_encrypt(3)AES_decrypt(3) 等低级加密函数。应用程序应改为使用高级 EVP API EVP_EncryptInit_ex(3)EVP_EncryptUpdate(3)EVP_EncryptFinal_ex(3)EVP_DecryptInit_ex(3)EVP_DecryptUpdate(3)EVP_DecryptFinal_ex(3)

已弃用的低级摘要函数

长期以来,非正式地不鼓励使用SHA1_Init(3) 等低级摘要函数。应用程序应使用高级 EVP API EVP_DigestInit_ex(3)EVP_DigestUpdate(3)EVP_DigestFinal_ex(3)或快速一次性EVP_Q_digest(3)

请注意,函数SHA1(3)SHA224(3)SHA256(3)SHA384(3)SHA512(3)已更改为使用EVP_Q_digest(3)的宏。

已弃用的低级签名函数

长期以来,非正式地不鼓励使用DSA_sign(3) 等低级签名函数。相反,应用程序应使用EVP_DigestSign(3)EVP_DigestVerify(3)。另请参见EVP_SIGNATURE-RSA(7)EVP_SIGNATURE-DSA(7)EVP_SIGNATURE-ECDSA(7)EVP_SIGNATURE-ED25519(7)

已弃用的低级 MAC 函数

低级 mac 函数(例如CMAC_Init(3))已被弃用。应用程序应使用新的EVP_MAC(3)接口,使用EVP_MAC_CTX_new(3)EVP_MAC_CTX_free(3)EVP_MAC_init(3)EVP_MAC_update(3)EVP_MAC_final(3)或单次 MAC 函数EVP_Q_mac(3)。请参见EVP_MAC(3)EVP_MAC-HMAC(7)EVP_MAC-CMAC(7)EVP_MAC-GMAC(7)EVP_MAC-KMAC(7)EVP_MAC-BLAKE2(7)EVP_MAC-Poly1305(7)EVP_MAC- Siphash(7)了解更多信息。

请注意,出于兼容性目的,一次性方法 HMAC() 仍然可用,但如果需要库上下文,也可以使用 EVP_Q_MAC 来替换。

已弃用的低级验证函数

长期以来,诸如DH_check(3) 之类的低级验证函数一直被非正式地禁止使用。应用程序应改为使用高级 EVP_PKEY API,例如EVP_PKEY_check(3)EVP_PKEY_param_check(3)EVP_PKEY_param_check_quick(3)EVP_PKEY_public_check( 3)、 EVP_PKEY_public_check_quick(3) 、EVP_PKEY_private_check(3)EVP_PKEY_pairwise_check(3)

已弃用的低级密钥交换函数

许多低级函数长期以来一直被非正式地禁止使用。应用程序应使用EVP_PKEY_derive(3)。请参阅EVP_KEYEXCH-DH(7)EVP_KEYEXCH-ECDH(7)EVP_KEYEXCH-X25519(7)

已弃用的低级密钥生成函数

许多低级函数长期以来一直被非正式地禁止使用。应用程序应使用EVP_PKEY_keygen_init(3)EVP_PKEY_generate(3) ,如EVP_PKEY-DSA(7)EVP_PKEY-DH(7)EVP_PKEY-RSA(7)EVP_PKEY-EC(7)EVP_PKEY-X25519(7)中所述。还可以使用 “快速”一次性函数EVP_PKEY_Q_keygen(3)和最常见情况的宏:<EVP_RSA_gen(3)> 和EVP_EC_gen(3) 。

已弃用的低级按键读写函数

长期以来,非正式地不鼓励使用低级对象(例如 DSA)。应替换读取和写入这些低级对象的函数(例如 PEM_read_DSA_PUBKEY())。应用程序应使用OSSL_ENCODER_to_bio(3)OSSL_DECODER_from_bio(3)

已弃用的低级按键打印功能

长期以来,非正式地不鼓励使用低级对象(例如 DSA)。打印这些低级对象的函数(例如 DSA_print())应替换为等效的 EVP_PKEY 函数。应用程序应使用EVP_PKEY_print_public(3)EVP_PKEY_print_private(3)EVP_PKEY_print_params(3)EVP_PKEY_print_public_fp(3)EVP_PKEY_print_private_fp(3)EVP_PKEY_print_params_fp(3)之一。请注意,它们在内部使用OSSL_ENCODER_to_bio(3)OSSL_DECODER_from_bio(3)

已弃用的函数映射

以下函数在 3.0 中已被弃用。

针对提供的密钥和算法的 NID 处理

以下用于 NID(数字 ID)处理的函数已更改语义。

在应用程序中使用 FIPS 模块

有关详细信息,请参阅fips_module(7)OSSL_PROVIDER-FIPS(7)

OpenSSL 命令行应用程序更改

新应用

openssl kdf使用新的EVP_KDF(3) API。openssl kdf使用新的EVP_MAC(3) API。

添加选项

-provider_path-provider可用于所有应用程序,并且可以多次使用来加载任何提供程序,例如“旧版”提供程序或第三方提供程序。如果使用,则还需要在需要时指定“默认”提供程序。-provider_path必须-provider选项之前指定。

列表应用 程序有许多新选项。有关详细信息, 请参阅openssl-list(1) 。

openssl ca使用的-crl_lastupdate-crl_nextupdate允许在生成的 CRL 中显式设置字段。

删除的选项

交互模式不再可用。

openssl passwd使用的-crypt 选项。openssl x509openssl dhparamopenssl dsaparamopenssl ecparam使用的-c选项。

其他变化

命令行应用程序的输出可能会有微小的变化。这些主要是大写和空白的变化。然而,在某些情况下,还存在其他差异。例如,openssl dhparam输出的 DH参数现在分别列出“P”、“Q”、“G”和“pcounter”,而不是“prime”、“generator”、“subgroup order”和“counter”。

读取密钥、证书和 CRL 的openssl命令现在会自动检测输入文件的 PEM 或 DER 格式,因此无需再显式指定输入格式但是,如果使用输入格式选项,则需要指定的格式。

openssl speed不再使用低级 API 调用。这意味着由于开销较高,某些性能数据可能无法与以前的版本相比较。这尤其适用于测量较小数据块的性能。

b<openssl dhparam>、openssl dsaopenssl gendsaopenssl dsaparamopenssl genrsaopenssl rsa已修改为使用 PKEY API。openssl genrsaopenssl rsa现在默认写入 PKCS #8 密钥。

默认设置

“SHA256”现在是openssl ts 使用的 TS 查询的默认摘要。

已弃用的应用程序

openssl rsautl已弃用,请改用openssl pkeyutlopenssl dhparamopenssl dsaopenssl gendsaopenssl dsaparamopenssl genrsaopenssl rsaopenssl genrsaopenssl rsa现在处于维护模式,不会添加新功能。

TLS 变更

  • 添加了 TLS 1.3 FFDHE 密钥交换支持

    这使用 DH 安全素数命名组。

  • 支持完全“可插入”的 TLSv1.3 组。

    这意味着提供商可以提供自己的组实现(使用“密钥交换”或“密钥封装”方法),这些实现将被 libssl 自动检测和使用。

  • SSL 和 SSL_CTX 选项现在是 64 位而不是 32 位。

    用于获取和设置 SSL 和 SSL_CTX 对象选项的函数签名从“unsigned long”更改为“uint64_t”类型。

    这可能需要更改源代码。例如,不再可能在预处理器条件中使用SSL_OP_宏值#if。但是仍然可以测试这些宏是否已定义。

    请参阅SSL_CTX_get_options(3)SSL_CTX_set_options(3)SSL_get_options(3)SSL_set_options(3)

  • SSL_set1_host() 和 SSL_add1_host() 更改

    这些函数现在采用 IP 文字地址和实际主机名。

  • 添加了 SSL 选项 SSL_OP_CLEANSE_PLAINTEXT

    如果设置了该选项,openssl 将在将内部缓冲区中的纯文本字节传递给应用程序后清除(清零)它们。请注意,应用程序仍然负责清理其他副本(例如:SSL_read(3)接收的数据)。

  • 默认情况下禁用客户端发起的重新协商。

    要允许它,请使用-client_renegotiation选项、SSL_OP_ALLOW_CLIENT_RENEGOTIATION标志或ClientRenegotiation适当的配置参数。

  • TLS 连接现在默认需要安全重新协商

    现在默认情况下需要支持 RFC 5746 安全重新协商才能成功实现 SSL 或 TLS 连接。需要能够连接到旧版对等点的应用程序需要显式设置 SSL_OP_LEGACY_SERVER_CONNECT。因此,SSL_OP_LEGACY_SERVER_CONNECT 不再设置为 SSL_OP_ALL 的一部分。

  • 组合配置选项 no-ec 和 no-dh 不再禁用 TLSv1.3

    通常,如果 OpenSSL 没有 EC 或 DH 算法,则它无法支持 TLSv1.3 的连接。然而,OpenSSL 现在通过提供商支持“可插入”组。因此,即使没有内置的,第三方提供商也可以提供组实现。尝试在此类构建中创建 TLS 连接而不在运行时禁用 TLSv1.3 或使用第三方提供程序组可能会导致握手失败。可以使用“no-tls1_3”配置选项在编译时禁用 TLSv1.3。

  • SSL_CTX_set_ciphersuites() 和 SSL_set_ciphersuites() 更改。

    这些方法现在忽略未知的密码。

  • 安全回调更改。

    安全回调可通过应用程序代码自定义,支持安全操作 SSL_SECOP_TMP_DH。它被定义为在“other”参数中采用 EVP_PKEY。在大多数地方,这就是通过的。所有这些地方都发生在服务器端。然而,此安全操作有一个客户端调用,并且它传递了一个 DH 对象。根据 SSL_SECOP_TMP_DH 的定义,这是不正确的,并且与所有其他位置不一致。因此,此客户端调用已更改为传递 EVP_PKEY。

  • 新的 SSL 选项 SSL_OP_IGNORE_UNEXPECTED_EOF

    引入了 SSL 选项 SSL_OP_IGNORE_UNEXPECTED_EOF。如果设置了该选项,则忽略意外的 EOF,它假装收到了关闭通知,因此返回的错误变为 SSL_ERROR_ZERO_RETURN。

  • TLS 中基于 SHA1 和 MD5 的签名的安全强度已降低。

    这会导致 SSL 3、TLS 1.0、TLS 1.1 和 DTLS 1.0 不再在默认安全级别 1 下工作,而是需要安全级别 0。可以使用带有 的密码字符串或调用 SSL_CTX_set_security_level(3) 来更改@SECLEVEL安全级别。这也意味着,如果 ClientHello 中缺少签名算法扩展,那么在安全级别 1 的 TLS 1.2 中,握手将会失败。这是因为,虽然此扩展是可选的,但未能提供意味着 OpenSSL 将回退到默认设置签名算法。此默认集需要 SHA1 的可用性。

  • 安全级别 1 及以上不再允许使用 SHA1 签名的 X509 证书。

    在 TLS/SSL 中,默认安全级别为 1。可以使用带有 的密码字符串@SECLEVEL或调用SSL_CTX_set_security_level(3)进行设置。如果叶证书是使用 SHA-1 签名的,并且不首先降低安全级别,则对SSL_CTX_use_certificate(3) 的调用将会失败。在 TLS/SSL 之外,默认安全级别为 -1(实际上为 0)。可以使用X509_VERIFY_PARAM_set_auth_level(3)或使用命令的 -auth_level选项进行设置。

SEE ALSO

fips_模块(7)

HISTORY

该迁移指南是为 OpenSSL 3.0 创建的。

版权所有 2021-2023 OpenSSL 项目作者。版权所有。

根据 Apache License 2.0(“许可证”)获得许可。除非遵守许可证,否则您不得使用此文件。您可以在源代码分发版或/source/license.html的 LICENSE 文件中获取副本。