译|王祖熙(花名:金九)
蚂蚁集团开发工程师
负责国产化密码库 Tongsuo 的开发和维护**专注于密码学、高性能网络、网络安全等领域
本文 4830 字 阅读 13 分钟
本文翻译 OpenSSL 官网文档:https://www.openssl.org/docs/OpenSSL300Design.html
Tongsuo-8.4.0 是基于 OpenSSL-3.0.3 开发,所以本文对 Tongsuo 开发者同样适用,内容丰富,值得一读!
由于文章篇幅较长,今天发布的是介绍、术语和架构三部分内容,后续内容将随每周推送完整发布,请持续关注铜锁公众号。
1►介绍
这份文件概述了 OpenSSL 3.0 的设计,它是在 1.1.1 版本之后的又一个版本。阅读本文需要您已经熟悉名为“OpenSSL 战略架构”的文件,并具备对 OpenSSL 1.1.x 的工作知识。
OpenSSL 3.0 版本对大多数现有应用程序影响很小;几乎所有性能良好的应用程序都只需重新编译即可。
OpenSSL 3.0 中的大部分改动都是内部架构重组,以促进建立一个可长期支持的加密框架,从而更好地将算法实现与算法 API 分离开来。这些结构性改动还有助于提高 OpenSSL FIPS 密码模块 3.0 的可维护性。
在 OpenSSL 3.0 中,目前标记为弃用 (deprecated) 的 API 不会被移除。
在 OpenSSL 3.0 中,许多额外的低级函数将被标记为弃用 (deprecated) 的 API。
OpenSSL 3.0 将同时支持应用程序具有处于 FIPS 模式 (使用 OpenSSL FIPS 密码模块 3.0) 和非 FIPS 模式的 TLS 连接。
有关 3.0 版本的更多最新信息,请参考https://www.openssl.org/docs上的链接。
2►术语
以下术语按字母顺序在本文中使用,简要定义如下:
-
算法 (Algorithm) :有时称为密码算法,是执行一组操作 (如加密或解密) 的方法。我们使用这个术语时是抽象的,通常通过名称 (例如“aes-128-cbc”) 来表示一个算法。
-
算法实现 (Algorithm implementation) :有时简称为实现 (implementation) ,是算法的具体实现。这主要以代码形式表示为一组函数。
-
CAVS 是密码算法验证系统。这是一种工具,用于测试密码实现是否符合 FIPS 标准。
-
CMVP 是密码模块验证程序。这个过程验证密码实现是否符合 FIPS 标准。
-
EVP 是由 libcrypto 实现的一系列 API,使应用程序能够执行密码操作。EVP API 的实现使用 Core 和 Provider 组件。
-
Core 是 libcrypto 中的一个组件,使应用程序能够访问 Provider 提供的算法实现。
-
CSP 是关键安全参数 (Critical Security Parameters) 。这包括在未经授权的披露或修改的情况下可能损害模块安全性的任何信息 (例如私钥、密码、PIN 码等) 。
-
显式获取 (Explicit Fetch) 是一种查找算法实现的方法,应用程序通过显式调用来定位实现并提供搜索条件。
-
FIPS 是联邦信息处理标准 (Federal Information Processing Standards) 。这是由美国政府定义的一组标准。特别是 FIPS 140-2 标准适用于密码软件。
-
FIPS 模块是经过 CMVP 验证符合 FIPS 标准的密码算法实现。在 OpenSSL 中,FIPS 模块以 Provider 的形式实现,并以可动态加载模块的形式提供。
-
隐式获取 (Implicit Fetch) 是一种查找算法实现的方法,应用程序不会显式调用来定位实现,因此会使用默认的搜索条件。
-
完整性检查 (Integrity Check) 是在加载 FIPS 模块时自动运行的测试。模块会对自身进行校验,并验证是否被恶意修改。
-
KAS 是密钥协商方案 (Key Agreement Scheme) 。它是两个通信方协商共享密钥的方法。
-
KAT 是已知答案测试 (Known Answer Tests) 。它是用于对 FIPS 模块进行健康检查的一组测试。
-
libcrypto 是 OpenSSL 实现的一个共享库,为应用程序提供各种与密码学相关的功能。
-
libssl 是 OpenSSL 实现的一个共享库,为应用程序提供创建 SSL/TLS 连接的能力,可以作为客户端或服务器。
-
库上下文 (Library Context) 是一个不透明结构,保存库的“全局”数据。
-
操作 (Operation) 是对数据执行的一类函数,如计算摘要、加密、解密等。一个算法可以提供一个或多个操作。例如,RSA 提供非对称加密、非对称解密、签名、验证等。
-
参数 (Parameters) 是一组与实现无关的键值对,用于在 Core 和 Provider 之间传递对象数据。例如,它们可以用于传输私钥数据。
-
POST 指的是 FIPS 模块的上电自检 (也称为开机自检) ,在安装、上电 (即每次为应用程序加载 FIPS 模块时) 或按需运行。这些测试包括完整性检查和 KAT。如果 KAT 在安装时成功运行,则在上电时不需要再次运行,但始终执行完整性检查。
-
属性 (Properties) 用于 Provider 描述其算法实现的特性。它们还用于应用程序查询以查找特定实现。
-
Provider 是提供一个或多个算法实现的单元。
-
Provider 模块是以可动态加载模块形式的 Provider。
3►架构
架构应具备以下特性:
-
公共服务 (Common Services) 是应用程序和 Provider 共用的构建模块,例如 BIO、X509、SECMEM、ASN.1 等。
-
Provider 实现密码算法和支持服务。一个算法可能由多个操作组成 (例如 RSA 可能有“加密”、“解密”、“签名”、“验证”等) 。同样,一个操作 (例如“签名”) 可以由多个算法实现,比如 RSA 和 ECDSA。Provider 包含了算法的密码原语实现。此版本将包括以下 Provider:
a. 默认 Provider (Default) ,包含当前非遗留 (non-legacy) 的 OpenSSL 密码算法;这将作为内置部分 (即 libcrypto 的一部分) 。
b. 遗留 Provider (Legacy) ,包含旧算法的实现 (例如 DES、MDC2、MD2、Blowfish、CAST) 。
c. FIPS Provider,实现 OpenSSL FIPS 密码模块 3.0;可以在运行时动态加载。
-
Core 使应用程序 (和其他 Provider) 能够访问 Provider 提供的操作。Core 是定位操作的具体实现的机制。
-
协议实现,例如 TLS、DTLS。
本文档中有许多关于“EVP API”的引用。这指的是“应用级别”的操作,例如公钥签名、生成摘要等。这些函数包括 EVP_DigestSign、EVP_Digest、EVP_MAC_init 等。EVP API 还封装了执行这些服务所使用的密码对象,例如 EVP_PKEY、EVP_CIPHER、EVP_MD、EVP_MAC 等等。Provider 为后者集合实现了后端功能。这些对象的实例可以根据应用程序的需求隐式或显式地绑定到 Provider 上。下面的 Provider 设计部分将详细讨论。
架构具有以下特点:
-
EVP 层是对 Provider 中实现的操作的薄封装,大多数调用会直接传递,几乎没有预处理或后处理过程。
-
将提供新的 EVP API,以影响 Core 如何选择 (或查找) 要在任何给定 EVP 调用中使用的操作的实现方式。
-
以与实现无关的方式在 libcrypto 和 Provider 之间传递信息。
-
将弃用遗留 API (例如不通过 EVP 层的低级密码 API) 。存在针对非遗留算法的遗留 API (例如 AES 不是遗留算法,但 AES_encrypt 是遗留 API) 。
-
OpenSSL FIPS 密码模块将作为动态加载的 Provider 实现,它将是自包含的 (即只能依赖于系统运行时库和核心提供的服务) 。
概念组件视图
OpenSSL 架构中的概念组件概述如下图所示。请注意,图中组件的存在并不意味着该组件是公共 API 或用于直接访问或使用的最终用户的组件。
新的组件 (在先前架构中不存在) 如下所示:
-
Core:这是一个基本组件,将对操作 (如加密) 的请求连接到提供该操作的 Provider。它提供了定位实现指定操作的算法的能力,给定一组实现必须满足的属性。例如,加密算法的属性至少包括“fips”。
-
默认 Provider (Default Provider) :实现了一组默认算法。
-
FIPS Provider:实现了经过 FIPS 验证的一组算法,并通过核心提供访问。这包括以下支持服务:
-
POST:上电自检,包括:
KAT:已知答案测试
完整性检查
-
低级实现 (Low Level Implementations) :实际实现密码原语的一组组件,以满足 FIPS 规定的自包含要求。
-
遗留 Provider (Legacy Provider) :提供了旧算法的实现,将通过 EVP 级别的 API 暴露出来。
-
第三方 Provider (3rd Party Providers) :最终,第三方可能会提供自己的 Provider。第三方 Provider 与任何其他 Provider 一样,实现了一组算法,可以通过 Core 访问,并对应用程序和其他 Provider 可见。
-
空 Provider (Null Provider) :一个什么都不做的 Provider,这对于测试正确使用库上下文非常有用。
-
基础 Provider (Base Provider) :用于密钥序列化的 Provider。FIPS Provider 需要它,因为它本身不包含加载密钥的方法。基础 Provider 也嵌入在默认 Provider服务器托管网 中。
打包视图
上述概念组件视图中描述的各个组件在物理上打包为:
- 可由用户使用的可执行应用程序
- 供应用程序使用的库
- 供 Core 使用的可动态加载模块
OpenSSL 3.0 将提供多种不同的打包选项 (例如一个名为 libcrypto 的单一库,包含除 FIPS Provider 之外的所有内容,以及所有 Provider 作为单独的可动态加载模块) 。
哪些可动态加载模块被注册、使用或可用可以在运行时进行配置,以下图示根据物理打包描述了架构:
本版本引入的物理打包如下:
-
FIPS 模块:该模块包含了实现了一组经过 FIPS 验证的算法,并通过 Core 可访问的 FIPS Provider。FIPS Provider 即 OpenSSL FIPS Cryptographic Module 3.0。
我们不会试图阻止用户出错,但我们会考虑典型用户的使用情况和“安全性”。默认情况下,将构建并安装 FIPS Provider。
我们将能够执行安全检查,以检测用户是否以对 FIPS 有影响的方式修改了源代码,并在未提供覆盖选项的情况下 (尽力而为) 阻止构建 FIPS Provider。
我们需要确保存在一种机制,使最终用户能够确定他们对 FIPS 模块的使用是否符合正式验证的允许用途。
FIPS 模块的版本将与基础 OpenSSL 版本号对齐,验证时的版本号取决于该版本。并非所有 OpenSSL 发布版本都需要更新 FIPS 模块。因此,当发布新的 FIPS 模块版本时,其版本号可能存在间隔或跳跃,与之前版本相比。
-
Legacy 模块:该模块包含了旧版算法的实现。
最初的计划是使用 Provider 的封装来构建引擎 (engines) ,以便在将 ENGINE 指针传递给某些函数时,使其像往常一样工作,并在充当默认实现时作为 Provider。在开发过程中的调查显示,这种方法存在问题的边缘情况。目前的解决方法是,当进行 EVP 调用时,目前存在两个代码路径。对于引擎 (engines) 的支持,使用“遗留密钥”的旧代码。长服务器托管网期计划是从代码库中删除引擎 (engines) 和遗留代码路径。一旦删除引擎 (engines) ,任何作为引擎 (engines) 编写的内容都需要重新编写为 Provider。
下周我们将带来 “Core 和 Provider 设计” 部分内容,等不及的小伙伴,可以查看铜锁语雀中的全篇文档哦:https://www.yuque.com/tsdoc/ts/openssl-300-design#AP9Lt
铜锁/Tongsuo Star 一下✨: https://github.com/Tongsuo-Project/Tongsuo
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
延迟解析:V8是如何实现闭包的? 在编译JavaScript代码的过程中,V8并不会一次性将所有的JavaScript解析为中间代码,这主要是基于以下两点:首先,如果是一次性解析和编译所有代码,会影响首次编译的时间,会大大增加用户等待时间。其次,解析完成的字节…