OpenSSL 3.0

2020-05-29 10:03:42

OpenSSL 3.0是目前正在开发的OpenSSL的下一个版本。本页面旨在为下载alpha/beta版本或计划从先前版本的OpenSSL升级到3.0的用户提供备注集合。

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

在以前的版本中,OpenSSL是在双重OpenSSL和SSLeay许可下许可的(这两个许可都适用)。从OpenSSL 3.0开始,这被Apache License v2所取代。

OpenSSL 1.1.1的主要变化之一是引入了提供者概念。提供者收集在一起并提供可用的算法实现。使用OpenSSL 3.0,可以通过编程或通过配置文件指定要为任何给定应用程序使用哪些提供程序。OpenSSL 3.0标配了4种不同的提供者。随着时间的推移,第三方可能会分发可以插入OpenSSL的其他提供程序。通过提供程序提供的所有算法实现都可以通过API集进行访问。它们不能使用低级API访问(见下文)。

OpenSSL过去提供了两组用于调用加密算法的API:EVP;API和低级API。EVP API通常设计为跨所有算法类型工作。低级API针对特定的算法实现。例如,EVP接口提供函数`EVP_EncryptInit_ex`、`EVP_EncryptUpdate`和`EVP_EncryptFinal`进行对称加密。这些函数可以与算法AES、ChaCha、3DES等一起使用。另一方面,要使用低级API进行AES加密,您必须调用AES特定函数,如`AES_SET_ENCRYPT_KEY`、`AES_ENCRYPT`等。3DES的功能不同。

长期以来,OpenSSL开发团队一直非正式地不鼓励使用低级API。然而,在OpenSSL3.0中,这一点变得更加正式。所有这样的低级API都已弃用。您仍然可以在应用程序中使用它们,但在编译过程中可能会开始看到不推荐使用的警告(这取决于编译器对此的支持)。不推荐使用的API可能会从OpenSSL的未来版本中删除,因此强烈建议您更新代码以使用EVP API。

一些通过EVP API可用的加密算法现在被认为是遗留的,强烈反对使用它们。这些遗留的EVP算法在OpenSSL 3.0中仍然可用,但不是默认情况下。如果要使用它们,则必须加载旧版提供程序。这可以像更改配置文件一样简单,也可以通过编程方式完成(见下文)。

支持提供程序的重构与用于支持引擎的API发生内部冲突,包括引擎API和创建或修改自定义方法的任何函数(例如,EVP_MD_METH_NEW、EVP_CIPHER_METH_NEW、EVP_PKEY_METH_NEW、RSA_METH_NEW、EC_KEY_METHOD_NEW等)。这些函数在OpenSSL 3.0中已弃用,这些API的用户应该知道,使用它们可能会绕过提供商选择和配置,从而带来意想不到的后果。这与编写为使用OpenSSL 3.0 FIPS模块的应用程序特别相关,如下所述。强烈鼓励外部引擎的创建者和维护者重构代码,使用新的提供者API将引擎转换为提供者,并避免使用过时的方法。

OpenSSL版本控制方案在3.0版中有所更改。新的版本化方案具有以下格式:

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

证书管理协议(CMP,RFC 4210)的实施还包括CRMF(RFC 4211)和HTTP传输(RFC 6712)。

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

OpenSSL错误代码的功能代码部分不再相关,始终设置为零。相关函数已弃用。

堆栈和散列宏已被清除,因此类型安全包装器在任何地方声明一次即可实现。有关堆栈,请参阅https://www.openssl.org/docs/manmaster/man3/DEFINE_STACK_OF.html的手册页,希望一旦PR合并,很快就会有https://www.openssl.org/docs/manmaster/man3/DECLARE_LHASH_OF.html(但在撰写本文时还没有)。

有关如何构建和安装OpenSSL 3.0的说明,请参阅发行版顶部的INSTALL.md文件。还请参阅适用于您的特定平台的各种平台特定说明文件。

注意:OpenSSL 3.0 Alpha 1版本包含一个在发布过程中引入的错误,该错误会导致编译失败。有两种解决方法可供选择:

编辑分发顶部的版本文件以删除RELEASE_DATE行上日期周围的引号,即使该行如下所示:

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

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

3)移除您使用的底层接口。在这种情况下,您需要重写代码以改用EVP API。

从OpenSSL 1.0.2升级到OpenSSL 3.0可能要困难得多。除了上面关于从1.1.1升级一节中讨论的问题外,需要注意的主要事项包括:

1)从OpenSSL 1.0.2开始,构建和安装过程发生了重大变化。有关如何为您的平台构建和安装OpenSSL的说明,请查看安装顶部的文件INSTALL.md。如果适用于您的平台,还要签出同一目录中的各种注释文件。

2)在OpenSSL 3.0中,很多结构都是不透明的。结构定义已从公共头文件中删除,并移至内部头文件。实际上,这意味着您不能再堆栈分配某些结构。相反,它们必须是通过某个函数调用分配的堆(通常这些函数名有`_new`后缀)。此外,您必须使用";setter&34;或";getter";函数来访问这些结构中的字段。

EVP_MD_CTX*MD_CTX;MD_CTX=EVP_MD_CTX_NEW();IF(MD_CTX==NULL)/*错误*/;/*使用MD_CTX*/EVP_MD_CTX_FREE(MD_CTX);

3)添加了对TLSv1.3的支持,这对SSL/TLS应用程序有很多影响。有关更多详细信息,请参阅TLS1.3页面。

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

OpenSSL2.0FIPS对象模块是一个单独的下载,必须单独构建,然后集成到主OpenSSL 1.0.2构建中。在OpenSSL 3.0中,FIPS支持完全集成到OpenSSL的主线版本中,不再需要单独下载。您不需要采取单独的构建步骤来添加FIPS支持-它是默认构建的。您确实需要采取措施来确保您的应用程序使用的是OpenSSL 3.0中的FIPS模块。有关此配置的详细说明,请参阅下面的说明。

函数调用';fips_mode()';和';fips_mode_set()';已从OpenSSL 3.0中删除。您应该重写您的应用程序以不使用它们。请参阅下面关于如何编写应用程序以使用OpenSSL 3.0中的FIPS模块的部分。

一旦构建并安装了OpenSSL,您将需要采取明确的步骤来完成FIPS模块的安装(如果您希望使用它)。OpenSSL 3.0 FIPS支持是以FIPS提供程序的形式提供的,在Unix上,该提供程序位于一个`fips.so`文件中。在Windows上,这将称为`fips.dll`。安装OpenSSL 3.0后,此文件的默认位置在Unix上为';/usr/local/lib/ossl-module/fips.so';,在Windows上为';C:\Program Files\openssl\lib\ossl-module\fips.dll';。

要完成安装,您需要运行fipsinstall命令行应用程序。这做了两件事:

生成FIPS模块配置文件输出,其中包含有关模块的信息,如自检状态和模块校验和。

FIPS模块必须运行自检,并在要使用FIPS模块的每台计算机上生成FIPS模块配置文件输出。您不得将FIPS模块配置文件输出数据从一台计算机复制到另一台计算机。

$openssl fipsinstall-out/usr/local/ssl/fipsmode.cnf-module/usr/local/lib/ossl-module/fips.so-Provider_name fips-mac_name hmac-macopt摘要:SHA256-macopt hekey:00-Section_name fips_sect。

如果将OpenSSL安装到不同的位置,则需要相应地调整输出和模块路径。

使用OpenSSL 1.1.1编写的应用程序大多只能使用OpenSSL 3.0。但是,如果您想要利用OpenSSL 3.0提供的一些新功能,则需要进行更改。为此,您需要了解OpenSSL 3.0中引入的一些新概念。

可以将库上下文视为OpenSSL操作的作用域。所有功能都在库上下文的范围内运行。多个库上下文可以同时存在,并且每个库上下文可以进行不同的配置。库上下文由新引入的openssl_ctx类型表示。请参阅此处的手册页。

OpenSSL中引入了许多接受OPENSSL_CTX参数的新函数。在许多情况下,这些函数是1.1.1中存在的一些其他函数的变体,它们的工作方式大致相同-只是它们现在在给定库上下文的范围内操作。

所有应用程序都可以使用默认库上下文。此库上下文始终存在,如果您未以其他方式指定,则这是将使用的库上下文。任何接受OPENSSL_CTX值作为参数的函数都将接受该参数的值NULL,以便引用默认库上下文。您还可以通过openssl_ctx_new()函数显式创建新文件。有关详细信息,请参阅手册页。

配置文件影响给定库上下文。很可能正在使用多个库上下文,每个库上下文都配置了不同的配置文件(请参见手册页上描述的openssl_ctx_load_config()函数)。

提供程序是算法实现的容器。每当通过EVP API使用加密算法时,都会选择提供者。实际上,正是提供程序实现完成了所需工作。有四个提供程序随OpenSSL一起分发。在未来,我们希望第三方分发他们自己的提供者,这些提供者可以动态地添加到OpenSSL中。在这里的手册页上可以找到有关编写提供程序的文档。

默认提供程序。它收集了所有标准的内置OpenSSL算法实现。如果应用程序没有明确指定任何其他内容(例如,在应用程序中或通过配置),则这是将使用的提供程序。如果还没有加载其他提供程序,当我们第一次尝试从提供程序获取算法时,它会自动加载。如果已经加载了另一个提供程序,则不会自动加载该提供程序。因此,如果您希望将其与其他提供程序结合使用,则必须显式加载它。这是一个内置的提供程序,这意味着它内置于libcrypto中,而不是作为单独的模块存在。

传统提供程序。这是不再常用或强烈建议不要使用的遗留算法的集合。但是,出于向后兼容性的原因,某些应用程序可能需要使用这些算法。默认情况下不加载此提供程序。这可能意味着,某些从早期版本的OpenSSL升级的应用程序可能会发现某些算法不再可用,除非它们显式加载旧版提供程序。传统提供者中的算法包括MD2、MD4、MDC2、RMD160、CAST5、BF(Blowfish)、IDEA、SEED、RC2、RC4、RC5和DES(但不包括3DES)。

FIPS提供商。它包含可从默认提供程序获得的算法实现的子集。此提供程序中提供的算法符合FIPS标准。此提供程序将通过FIPS140-2验证。在某些情况下,与默认提供程序中的等效算法相比,此提供程序中的算法实现之间可能存在细微的行为差异。这通常是为了符合FIPS标准。

空提供程序。此提供程序是libcrypto的内置提供程序,不包含算法实现。为了保证不自动加载默认提供程序,可以改为加载空提供程序。如果您正在使用非默认库上下文,并且希望确保不会意外使用默认库上下文,这会很有用。

可以在OpenSSL配置文件中指定要加载的提供程序。有关如何通过配置文件配置提供程序以及如何自动激活它们的信息,请参阅此处的手册页。这是在默认库上下文中加载和激活传统提供程序和默认提供程序的最小配置文件示例。

openssl_conf=openssl_init[openssl_init]Providers=Provider_sect[Provider_sect]默认=default_sect遗留=Legacy_sect[default_sect]activate=1。

也可以通过编程方式加载它们。例如,您可以将遗留提供程序加载到默认库上下文中,如下所示。请注意,一旦将提供程序显式加载到库上下文中,将不再自动加载默认提供程序。因此,您通常还希望显式加载默认提供程序,如下所示:

#include<;stdio.h>;#include<;stdlib.h>;#include<;openssl/provider.h>;int main(Void){OSSL_Provider*Legacy;OSSL_Provider*Deflt;/*将多个提供程序加载到默认(空)库上下文*/Legacy=OSSL_PROVIDER_LOAD(NULL,";Legacy&34;);如果(Legacy=NULL){printf(&。}deflt=OSSL_PROVIDER_LOAD(NULL,";DEFAULT";);IF(DEFLT==NULL){printf(";无法加载默认提供程序\n";);OSSL_PROVIDER_UNLOAD(旧版);EXIT(EXIT_FAILURE);}/*应用程序的其余部分*/OSSL_PROVIDER_UNLOAD(旧版);OSSL_PROVIDER_UNLOAD(DEFLT);EXIT(EXIT_SUCCESS);}

为了使用加密算法(如AES),必须首先从已加载到正在使用的库上下文中的可用提供程序中获取该算法的实现。这可以隐式或显式完成。

使用隐式获取,应用程序不需要执行任何特殊操作。算法实现将由相关API自动获取。例如:

EVP_MD_CTX*mdctx;mdctx=EVP_MD_CTX_NEW();IF(mdctx==NULL)转到错误;IF(EVP_DigestInit_EX(mdctx,EVP_sha256(),NULL)!=1)转到错误;

在这段代码中,我们初始化摘要操作以使用SHA256算法。evp_DigestInit_ex()函数将在需要时自动从可用的提供程序获取SHA256算法的实现。它将使用默认库上下文和默认属性查询字符串(见下文)来执行此操作。

通过显式获取,应用程序获取要预先使用的实现,然后将其传递给相关的EVP API。例如:

EVP_MD_CTX*mdctx;EVP_MD*sha256;mdctx=EVP_MD_CTX_NEW();IF(mdctx==NULL)GOTO ERR;/**此处将库CTX设置为NULL会将算法从*加载到默认库上下文中的提供程序中提取*/sha256=EVP_MD_FETCH(NULL,";SHA2-256";,NULL);IF(sha256=NULL)*/sha256=EVP_MD_FETCH(NULL,";SHA2-256";,NULL);IF(sha256=NULL)。/*显式拉取返回必须释放的动态对象*/EVP_MD_FREE(Sha256);

在本例中,我们显式地从加载到默认库上下文中的一组可用提供程序中获取了SHA256的实现。

使用显式FETCH,我们可以另外提供一个属性查询,以进一步指定我们希望获得的实现。例如:

在这里,我们显式获取SHA256算法的FIPS验证实现。这样的实现存在于FIPS提供程序中,因此我们需要确保将FIPS提供程序加载到默认库上下文中才能成功。如果找不到与条件匹配的算法实现,则获取将失败。

有关详细信息,请参阅提供程序手册页中关于获取算法的部分:[1]。

如果不需要特定的属性查询,则可以为最后一个参数传递NULL。在任何情况下,提供的任何特性查询都会与默认特性查询组合在一起。如果未指定任何其他内容,则默认特性查询为空。但是,可以对此进行更改,以便每次提取都自动继承这些默认属性。默认属性可以通过编程方式设置,也可以通过配置文件设置。有关如何执行此操作的示例,请参阅与其他提供程序同时加载FIPS模块一节。

请注意,默认属性当前在OpenSSL 3.0 Alpha 1或Alpha 2版本中不起作用。

OpenSSL可以通过多种不同的方式与FIPS模块结合使用。哪种方法是正确的,将取决于你自己的具体情况和你试图实现的目标。请注意,旧函数fips_mode()和fips_mode_set()不再存在,因此如果您使用它们,则必须从应用程序中删除它们。

一种简单的方法是使所有使用OpenSSL的应用程序在默认情况下仅将FIPS模块用于加密算法。

这种方法完全可以通过配置来实现。只要应用程序是根据OpenSSL 3.0构建和链接的,并且不覆盖默认配置文件或其设置的加载,则它们将自动开始使用FIPS模块,而不需要进一步更改任何代码。

为此,必须修改默认的OpenSSL配置文件。此配置文件的位置将取决于平台以及构建过程中提供的任何选项。您可以通过运行以下命令检查配置文件的位置:

注意:许多操作系统默认安装OpenSSL。没有Correc是一种常见的错误。

..