本文档来自: https://zread.ai/openssl/openssl
来源: https://zread.ai/openssl/openssl/1-overview
欢迎来到 OpenSSL,这是业界标准的开源加密工具包,为整个互联网的安全通信提供支持。本全面概述将向你介绍 OpenSS L 的基础架构、核心组件和功能,正是这些特性使其成为现代安全基础设施的基石。

OpenSSL 官方 Logo
OpenSSL 是一个强大、商业级、功能齐全的开源工具包,用于实现安全通信协议。它提供了传输层安全(TLS)、数据报 TLS(DTLS)和新兴的 QUIC 协议的实现,所有这些都构建在强大的通用加密库之上README.md。
该工具包的渊源可追溯至由 Eric A. Young 和 Tim J. Hudson 开发的 SSLeay 库,现已发展为全面的加密解决方案,为从 Web 服务器到移动应用的各类应用提供安全保障。
OpenSSL 围绕三个主要组件构建,这些组件协同工作以提供完整的加密和协议功能:
libssl库实现了所有主要的安全通信协议及其最新版本:
libcrypto库作为加密引擎,提供:
openssl命令行工具是加密任务的通用"瑞士军刀",包括:
OpenSSL 遵循组织良好的目录结构,分离关注点并便于维护:
项目结构说明:
从 OpenSSL 3.0 开始,工具包引入了提供程序架构,将算法实现模块化:
提供程序架构优势:
提供程序架构允许第三方分发自己的加密实现,这些实现可以动态加载到 OpenSSL 中,从而支持自定义算法和硬件加速模块。
提供程序是算法实现的容器,当通过高级 API 执行加密操作时会被选择README-PROVIDERS.md。
OpenSSL 3.2 引入了客户端 QUIC 支持,服务器端 QUIC 功能在 OpenSSL 3.5 中添加。这使得 OpenSSL 成为现代安全传输协议的综合解决方案README-QUIC.md。
要开始你的 OpenSSL 之旅,按照文档的逻辑顺序进行:
针对特定平台的指导,请参考:
OpenSSL 为开发者提供丰富的资源:
demos/目录中的源代码示例
demos/guide目录包含 OpenSSL 指南的完整源代码示例,是学习实际实现模式的绝佳起点。
OpenSSL 采用Apache License 2.0许可证,允许商业和非商业使用,同时保持开源原则README.md。
有关支持选项和社区参与,请查阅SUPPORT文件,其中详细说明了不同类型需求的适当渠道。
OpenSSL 通过社区贡献持续发展,开发工作通过 GitHub pull requests 进行协调。有兴趣贡献者应查看CONTRIBUTING指南,了解开发流程的详细说明。
来源: https://zread.ai/openssl/openssl/2-quick-start
欢迎使用 OpenSSL!这个全面的加密工具包为你提供了实现安全通信和加密操作所需的一切。本快速入门指南将帮助你快速上手并掌握 OpenSSL 的核心功能。
OpenSSL 由三个主要组件组成,它们协同工作以提供完整的加密能力:
核心组件:
在安装 OpenSSL 之前,请确保你已具备:
对于 Unix/Linux/macOS 系统:
$ ./Configure
$ make
$ make test
$ sudo make install
对于使用 Visual Studio 的 Windows 系统:
$ perl Configure VC-WIN64A
$ nmake
$ nmake test
$ nmake install
在安装前务必运行
make test,以确保 OpenSSL 在你的系统上正确构建。这能及早发现大多数配置问题。
安装完成后,你可以立即通过命令行界面开始使用 OpenSSL。以下是最常见的操作:
openssl genpkey -algorithm RSA -out private.key -pkeyopt rsa_keygen_bits:2048
# 生成 EC 私钥
openssl genpkey -algorithm EC -out ec_private.key -pkeyopt ec_paramgen_curve:secp384r1
openssl req -new -x509 -key private.key -out certificate.crt -days 365
# 加密文件
openssl enc -aes-256-cbc -salt -in plaintext.txt -out encrypted.enc
# 解密文件
openssl enc -aes-256-cbc -d -in encrypted.enc -out decrypted.txt
# 计算 SHA-256 哈希值
openssl dgst -sha256 -out hash.txt file.txt
# 验证文件完整性
openssl dgst -sha256 -verify signature.sig file.txt
OpenSSL 命令按功能进行组织:
req,x509,ca,verifygenpkey,rsa,ec,dsaenc,rsautl,pkeyutldgst,sha256,md5s_client,s_server,s_timepkcs12,pkcs8,caOpenSSL 在demos/目录中提供了全面的演示代码demos/README.txt。这些示例展示了正确的 API 用法:
demos/bio/和demos/sslecho/中的简单客户端/服务器实现demos/quic/和demos/http3/中的 QUIC 和 HTTP/3 示例demos/certs/和demos/pkcs12/中的证书创建和 PKCS#12 操作
OpenSSL 示例代码结构图
# 克隆仓库用于开发
git clone https://github.com/openssl/openssl.git
cd openssl
# 配置开发环境(包含调试功能)
./Configure --debug --prefix=/usr/local/ssl
# 启用演示代码构建
./Configure enable-demos
make
# 测试 HTTPS 连接
openssl s_client -connect example.com:443 -servername example.com
# 使用特定 TLS 版本测试
openssl s_client -connect example.com:443 -tls1_3
# 启动测试服务器
openssl s_server -accept 4433 -cert server.crt -key server.key
# 创建 CA 私钥
openssl genpkey -algorithm RSA -out ca.key -pkeyopt rsa_keygen_bits:4096
# 创建 CA 证书
openssl req -new -x509 -key ca.key -out ca.crt -days 3650
# 签署证书请求
openssl ca -in request.csr -out signed.crt -cert ca.crt -keyfile ca.key
对于生产环境,始终将 OpenSSL 安装到自定义前缀,以避免与其他应用程序可能依赖的系统 OpenSSL 版本发生冲突。
既然你已经掌握了基础知识,可以探索以下领域:
如需完整文档,请访问docs.openssl.org上的官方 OpenSSL 手册页,或浏览demos/目录中的演示代码,查看常见加密任务的实用实现。
来源: https://zread.ai/openssl/openssl/3-installation-and-configuration
本综合指南涵盖了在所有受支持平台上安装和配置 OpenSSL 的完整过程。无论你是初次设置 OpenSSL 的初级开发者,还是自定义构建的资深用户,本文档都提供了在你的环境中成功部署 OpenSSL 所需的关键步骤和选项。
对于大多数用户,基本的安装过程包括三个简单步骤:配置、构建和安装。具体命令因平台而异,但基本流程保持一致。
核心构建过程包括为你的系统配置 OpenSSL、编译源代码以及运行测试以验证安装。
构建流程说明:
./Configure 根据平台生成构建文件$ ./Configure
$ make
$ make test
$ perl Configure
$ mms
$ mms test
对于 Visual Studio 用户,打开开发者命令提示符:
$ perl Configure
$ nmake
$ nmake test
系统范围的安装步骤需要管理员权限。对于 Windows 用户,请根据你的体系结构选择合适的 Visual Studio 目标:
VC-WIN64A或VC-WIN64A-HYBRIDCRTVC-WIN32或VC-WIN32-HYBRIDCRT出于安全原因,请使用普通用户权限编译和测试 OpenSSL,然后仅在最终安装步骤时使用管理员权限。这可以防止构建过程中出现潜在的安全问题。
OpenSSL 提供了广泛的配置选项,用于根据特定需求、平台和用例自定义构建。
最常见的配置选项控制 OpenSSL 的安装位置:
--prefix=DIR/usr/localC:\Program Files\OpenSSL--openssldir=DIR/usr/local/sslC:\Program Files\Common Files\SSL--libdir=DIRliblib为避免与系统 OpenSSL 安装冲突,请安装到自定义位置:
$ ./Configure --prefix=/opt/openssl --openssldir=/usr/local/ssl
# OpenVMS
$ perl Configure --prefix=PROGRAM:[INSTALLS] --openssldir=SYS$MANAGER:[OPENSSL]
控制支持的 API 版本:
# 支持特定 API 版本
$ ./Configure --api=1.1.0
# 移除当前版本及之前的已弃用 API
$ ./Configure no-deprecated
# 移除特定的已弃用 API
$ ./Configure --api=1.1.0 no-deprecated
用于在一个平台上为另一个平台构建 OpenSSL:
# 交叉编译前缀
$ ./Configure --cross-compile-prefix=x86_64-w64-mingw32-
# 示例:
# Linux 到 Windows: --cross-compile-prefix=x86_64-w64-mingw32-
# Linux 到 MIPS: --cross-compile-prefix=mipsel-linux-gnu-
OpenSSL 通过启用/禁用标志提供对已启用功能的细粒度控制:
enable-brotlino-brotlienable-quicno-quicenable-fipsno-fipsenable-asanno-testsenable-ktlsno-asm# 最小安装
$ ./Configure no-shared no-threads no-tests
# 带调试的开发构建
$ ./Configure enable-asan enable-ubsan --strict-warnings
# 符合 FIPS 的构建
$ ./Configure enable-fips enable-fips-securitychecks
# 性能优化的构建
$ ./Configure enable-ktls enable-tfo enable-zstd
现代配置过程会自动检测你的平台:
# Unix/Linux/macOS
$ ./Configure [选项...]
# Windows 和 OpenVMS
$ perl Configure [选项...]
对于特定平台要求,列出可用配置:
$ ./Configure LIST # Unix
$ perl Configure LIST # 所有平台
然后选择你的特定目标:
$ ./Configure linux-elf [选项...]
$ ./Configure VC-WIN64A [选项...]
在与源码分离的目录中构建 OpenSSL:
# Unix 示例
$ mkdir /var/tmp/openssl-build
$ cd /var/tmp/openssl-build
$ /PATH/TO/OPENSSL/SOURCE/Configure [选项...]
# Windows 示例
$ C:
$ mkdir temp-openssl
$ cd temp-openssl
$ perl d:PATHTOOPENSSLSOURCEConfigure [选项...]
编译已配置的 OpenSSL:
# Unix
$ make
# OpenVMS
$ mms
# Windows
$ nmake
这将生成:
libcrypto.a和libssl.a(Unix 等效物)apps/目录中的openssl命令关键:始终从非特权账户运行测试:
# Unix
$ make test
# OpenVMS
$ mms test
# Windows
$ nmake test
从非特权账户运行测试是强制性的安全要求。这可以防止测试过程中出现潜在的权限提升漏洞。
安装已构建的组件:
# Unix
$ make install
# OpenVMS
$ mms install
# Windows
$ nmake install
Unix / Linux / macOS:
<PREFIX>/
├── bin/ # OpenSSL 二进制文件和实用程序
├── include/openssl/ # 头文件
├── lib/ # 库文件
├── share/man/man1/ # 命令手册页
├── share/man/man3/ # 库 API 手册页
├── share/man/man5/ # 配置格式手册页
├── share/man/man7/ # 其他手册页
└── share/doc/openssl/html/ # HTML 文档
Windows:
<PREFIX>/
├── bin/ # OpenSSL 二进制文件和 DLL
├── include/openssl/ # 头文件
├── lib/ # 静态库 (.lib)
└── ssl/ # 配置和证书
对于安装在非默认位置的情况,设置运行时库搜索路径:
# Linux/BSD
-Wl,-rpath,/custom/path
# Solaris
-R /custom/path
# AIX
-Wl,-R,/custom/path
# HP-UX
-Wl,+b,/custom/path
影响构建的关键环境变量:
CCgcc,clangCXXg++,clang++CFLAGS-O2 -march=nativeLDFLAGS-Wl,-rpath,/opt/libVC-WIN64AVC-WIN32VC-WIN64A-HYBRIDCRTVC-WIN32-HYBRIDCRTOpenVMS 使用 Digital Command Language (DCL) 语法和特定的文件命名约定:
$ perl Configure [选项...]
$ mms
$ mms test
$ mms install
为不受支持的系统创建自定义配置:
Configurations/YOURFILENAME.confConfigurations/README.md获取指导对于替代构建系统,使用自定义构建文件模板:
$ BUILDFILE=build.ninja perl Configure [选项...]
使用之前的设置重新运行配置:
$ ./Configure reconf
这将从configdata.pm重新加载保存的配置。
如果./Configure失败:
NOTES-*文件中的平台特定说明常见解决方案:
# 清理构建树
$ make clean # Unix
$ mms clean # OpenVMS
$ nmake clean # Windows
# 禁用汇编优化
$ ./Configure no-asm
# 使用通用编译器配置
$ ./Configure gcc # 或 cc
关键:始终以非特权用户身份运行测试。如果测试失败:
test/README.md获取特定于测试的指导成功安装后,继续你的 OpenSSL 之旅:
有关平台特定的安装详细信息和高级配置选项,请参考存储库根目录中的平台特定说明和综合性的INSTALL.md文件。
来源: https://zread.ai/openssl/openssl/4-basic-command-line-usage
OpenSSL 提供了一个全面的命令行界面,作为加密操作、证书管理和 SSL/TLS 连接测试的主要交互点。本指南介绍了 OpenSSL 的基本命令结构和常用操作,面向刚接触 OpenSSL 的开发者。
OpenSSL 命令行工具遵循一致的结构:openssl command [options] [arguments]。主入口实现在apps/openssl.c中,通过可用函数的哈希表处理命令调度。
OpenSSL 命令分为多个功能类别:
命令分类说明:
命令注册表由apps/progs.pl动态生成,它会扫描源文件中匹配*_main模式的函数并创建命令表。
RSA 密钥生成
openssl genrsa -out private.key 2048
此命令生成一个 2048 位的 RSA 私钥。实现在apps/genrsa.c中,选项定义在 [apps/genrsa.c#L49-L78]。默认密钥大小为 2048 位,如apps/genrsa.c#L27所指定。
证书信息显示
openssl x509 -in certificate.crt -text -noout
x509 命令提供全面的证书操作功能。关键选项定义在apps/x509.c#L118-L243中,包括文本显示、主题/颁发者打印和有效期检查。
文件加密
openssl enc -aes-256-cbc -in plaintext.txt -out encrypted.enc
enc 命令支持多种加密算法。选项定义在apps/enc.c#L83-L142中,通过这些参数处理加密算法选择和基于密码的密钥派生。
客户端连接测试
openssl s_client -connect example.com:443 -showcerts
s_client 命令是一个强大的 TLS 客户端,用于测试连接。其扩展选项定义在apps/s_client.c#L611-L848中,支持各种协议、证书验证和调试功能。
大多数 OpenSSL 命令遵循一致的 I/O 模式:
-in-in certificate.pem-out-out private.key-inform-inform DER-outform-outform PEM密码选项因命令而异,但通常包括:
-passin- 输入密码来源-passout- 输出密码来源-pass- 通用密码来源在生产环境中,使用
pass:前缀直接指定密码或使用env:引用环境变量,以避免密码在命令历史记录中暴露。
每个命令都支持内置帮助:
openssl help <command>
openssl <command> -help
帮助系统实现在apps/openssl.c#L395-L459中,提供特定于命令的选项文档。
掌握这些基本命令后,进一步探索:
命令行界面既是一个实用工具,也是理解 OpenSSL 全面加密能力的入口。
来源: https://zread.ai/openssl/openssl/5-unix-linux-installation
本指南提供了在 Unix/Linux 系统上安装 OpenSSL 的全面说明,涵盖了从基础安装到面向开发者的各种高级配置选项。
对于大多数用户,标准安装流程包含三个简单步骤:
$ ./Configure
$ make
$ make test
$ make install
这会将 OpenSSL 安装到默认位置/usr/local,并包含以下目录结构 [INSTALL.md#L205-L235]:
/usr/local/bin- OpenSSL 命令行工具/usr/local/lib- 库文件 (libcrypto.a,libssl.a)/usr/local/include/openssl- 头文件/usr/local/share/man- 手册页安装前务必运行
make test以验证构建是否正常工作。出于安全考虑,测试必须从非特权账户运行 [INSTALL.md#L1486-L1490]。
安装步骤说明:
为避免与系统 OpenSSL 安装冲突,建议安装到自定义位置:
$ ./Configure --prefix=/opt/openssl --openssldir=/usr/local/ssl
关键目录选项 [INSTALL.md#L349-L400]:
--prefix/usr/local--openssldir/usr/local/ssl--libdirlib安装到非默认位置时,可能需要使用
-Wl,-rpath,$(LIBRPATH)等选项设置运行时库路径,以确保应用程序能找到共享库 [NOTES-UNIX.md#L25-L50]。
OpenSSL 会自动检测你的平台和编译器。查看可用目标:
$ ./Configure LIST
手动选择平台 [INSTALL.md#L1370-L1395]:
$ ./Configure linux-x86_64 [options...]
threads,no-threadsshared,no-sharedzlib,zlib-dynamicenable-fips对于 Unix 系统,OpenSSL 使用 C 编译器进行链接,因此所有链接器选项必须与编译器兼容 [NOTES-UNIX.md#L3-L8]:
$ ./Configure --prefix=/usr/local/ssl '-Wl,-rpath,$(LIBRPATH)'
OpenSSL 支持在与源码分离的目录中构建 [INSTALL.md#L1418-L1444]:
$ mkdir /var/tmp/openssl-build
$ cd /var/tmp/openssl-build
$ /PATH/TO/OPENSSL/SOURCE/Configure [options...]
安装后,你的 OpenSSL 目录将包含 [INSTALL.md#L1497-L1537]:
<PREFIX>/
├── bin/
├── include/openssl/ # 头文件
├── lib/ # 库文件
├── share/man/ # 手册页
└── share/doc/openssl/html/ # HTML 文档
<OPENSSLDIR>/ # 通常为 /usr/local/ssl
├── certs/ # 证书存储
├── private/ # 私钥存储
└── misc/ # 实用脚本
如果遇到问题 [INSTALL.md#L1800-L1830]:
成功安装后:
安装完成后,你将获得一个完整的 OpenSSL 开发环境,可用于加密应用程序和 TLS/SSL 实现。
来源: https://zread.ai/openssl/openssl/6-latest-updates
OpenSSL以不间断的开发步伐持续前进,最近发布了3.6.0版本,并通过一系列提交修复了关键安全问题、性能回归和平台特定兼容性。让我们深入了解对开发者和系统管理员最重要的变更。
2025年10月发布的OpenSSL 3.6.0在后量子密码学准备方面标志着重要里程碑。根据官方发布说明,该版本为PKEY对象引入了NIST安全类别,使应用程序能够评估量子抗性级别(0-5,数值越高表示对量子攻击的保护越强)。
最显著的补充是LMS签名验证支持,符合NIST SP 800-208标准,在FIPS和默认提供程序中均可用。这种基于哈希的签名方案为固件签名和长期文档验证提供量子抗性。该版本还添加了EVP_SKEY不透明对称密钥对象,包含新API:EVP_KDF_CTX_set_SKEY()、EVP_KDF_derive_SKEY()和EVP_PKEY_derive_SKEY(),将对称密钥管理从原始字节数组中抽象出来。
破坏性变更包括要求使用C99兼容编译器(ANSI-C不再足够)和移除对VxWorks平台的支持。FIPS提供程序现在支持符合FIPS 186-5标准的确定性ECDSA,解决了签名生成中的一致性问题。
2025年底修复了三个关键漏洞:
no_proxy环境变量设置IPv6主机时,HTTP客户端越界读取。这个低严重性问题导致curl和wget等客户端工具崩溃。OpenSSL 3.6.0中出现了重大性能回归,影响了使用Coreutils的sha256sum的应用程序。根据issue #29340的记录,在支持SHA-NI的CPU上,该工具变得慢了3倍,因为提交1d770fc删除了非EVP API依赖的OPENSSL_cpuid_setup构造函数调用来进行CPU特性检测。
Coreutils维护人员确认这是初始化行为变更的意外副作用。这突显了一个更广泛的担忧:使用遗留低级API(如SHA256_Init)而非现代EVP接口的应用程序可能在没有显式初始化的情况下错过性能优化。
最近的提交显示了OpenSSL对平台多样性的承诺:
OpenSSL正在进行重大工具改进:
在issue #29353中发现了一个违反TLS 1.3 RFC 8446的问题。当接收到带有未经请求的StatusRequest扩展的ServerHello时,OpenSSL错误地返回UnsupportedExtension警报,而非RFC 8446第4.2节要求的IllegalParameter警报。这是由tlspuffin模糊测试团队在协议测试期间发现的。
出现了几个平台特定的构建问题:
no-deprecated选项时失败,由于MD5和SHA实现中缺少类型定义(issue #29357)。这影响了希望移除已弃用API的RISC-V嵌入式系统开发者。sendmmsg引用(issue #23751),因为此功能仅在AIX 7.2中添加。解决方法需要使用no-dgram配置选项。在issue #29355中报告了一个微小但令人困惑的不一致:openssl list -kem-algorithms显示MLKEM512,而openssl speed只接受ML-KEM-512。发现和基准测试工具之间的这种命名差异为探索后量子算法的开发者制造了不必要的摩擦。
OpenSSL项目的发展轨迹显示出日益关注:
最近SHA-NI检测的性能回归提醒我们,即使是善意的重构也可能产生意外后果。随着OpenSSL继续发展其提供程序架构并添加量子抗性算法,在现代化代码库的同时保持向后兼容性仍然是一个微妙的平衡。
对于生产部署,3.5 LTS分支仍然是保守选择,直到3.6版本成熟,而实验后量子密码学的开发者应该考虑3.6版本的功能,尽管可能存在一些成长的烦恼。
来源: https://zread.ai/openssl/openssl/7-issues-and-feedbacks
OpenSSL 作为保障互联网大部分通信安全的基石加密库,持续受到安全研究人员和更广泛开发者社区的严格审查。近期问题揭示了平台特定挑战、加密边界案例以及性能优化与安全性正确性之间持续存在的矛盾。
AIX 兼容性问题在近期反馈中仍是持续存在的主题。AIX 7.1 构建失败问题凸显了 OpenSSL 采用sendmmsg等新系统调用可能会破坏与旧操作系统的兼容性。这个可追溯到 2024 年 3 月的问题,展示了现代化代码库与维护向后兼容性之间的微妙平衡。同样,AIX 挂起测试用例显示了平台特定的网络实现如何导致测试套件失败,特别是在sendmmsg和recvmmsg功能方面。
旧版 MSVC 编译器上与_InterlockedExchangeAdd相关的Windows 编译问题(issue #21080)揭示了平台兼容性挑战的另一维度。虽然此问题最近已关闭,但它强调了 OpenSSL 的演进可能会淘汰旧的开发环境。
近期讨论凸显了加密实现中的关键安全考虑:
Coreutils SHA-NI 性能回归(issue #29340)说明了内部重构如何对依赖应用程序产生意外性能影响。特定提交中移除OPENSSL_cpuid_setup导致sha256sum出现 3 倍性能下降,展示了 OpenSSL 的内部优化如何影响更广泛的生态系统。
同样,RISC-V 上使用no-deprecated的交叉编译失败(issue #29357)揭示了维护传统支持与启用现代构建配置之间的矛盾。
openssl list和openssl speed命令之间的命名不一致性(issue #29355)代表了典型的可用性问题,算法标识符在发现和基准测试工具之间存在差异。这种看似微小的不一致性可能给使用后量子密码学实现的开发者带来显著摩擦。
openssl ca中的证书日期计算错误(issue #29363)展示了证书管理工具中的边界案例如何导致无效证书,特别是在处理像 BSI TR-03145-5 等标准要求的未来日期证书时。
几个问题指出了 OpenSSL 配置和文档中的持续挑战:
安全社区对 OpenSSL 的关注依然强烈,自主安全系统做出了重要贡献。根据AISLE 的研究,2025 年四个 OpenSSL CVE 中有三个是由其自主系统发现的:
这些发现凸显了即使是经过严格审计的代码库也可能隐藏长期存在的漏洞,特别是在传统代码路径和架构特定优化中。
协调披露和修补过程展示了安全研究人员与 OpenSSL 团队之间的有效协作。据Security Affairs报道,补丁已应用于七个活跃发布分支(3.5.4、3.4.3、3.3.5、3.2.6、3.0.18、1.1.1zd 和 1.0.2zm),显示了 OpenSSL 对维护其支持版本安全的承诺。
虽然 OpenSSL 官方的Twitter 存在仍然有限,但社区讨论在 Reddit 的r/openssl和各种 Stack Exchange 网站上蓬勃发展。GitHub Discussions平台显示了围绕性能问题的积极参与,维护者提供详细回复并引导用户访问性能仪表板。
更广泛的生态系统提供多个支持渠道:
ML-KEM 命名不一致性和预哈希 ML-DSA 支持请求表明社区对后量子密码学的兴趣日益增长。随着这些算法的成熟,OpenSSL 将面临越来越大的压力,需要提供一致、文档完善的实现。
添加clang-format 和 codespell 预提交钩子(commits d6f3733f和d70b22bf)反映了改进代码质量和可维护性的努力。然而,AIX 测试失败(issue #29352)表明平台特定的 CI/CD 挑战依然存在。
关于引入显式布尔类型的长期讨论(issue #17494)代表了 OpenSSL API 演进的更广泛问题。随着该库接近其第三个十年,平衡向后兼容性与现代 API 设计原则变得越来越具有挑战性。
OpenSSL 的问题概览揭示了一个成熟项目在安全、性能、兼容性和可用性的复杂交汇中航行。社区的参与——从详细的安全研究到实际的部署关注——展示了 OpenSSL 在全球基础设施中的关键作用。虽然最近的漏洞表明没有代码库能免受安全问题的影响,但项目响应式的维护实践和不断发展的安全生态系统为其持续演进提供了信心。
近期问题中的模式表明几个需要持续关注的领域:平台特定测试和兼容性、加密边界案例处理、API 一致性和文档完整性。随着 OpenSSL 继续适应新的加密标准和部署环境,保持创新与稳定性之间的平衡仍将是关键。
来源: https://zread.ai/openssl/openssl/8-about-contributors
OpenSSL 项目是全球最关键的开源密码学库之一,由一支专注的贡献者团队维护,团队成员在密码学、安全和软件开发领域拥有数十年的集体经验。让我们深入了解这个基础项目背后的关键人物及其背景。
作为 OpenSSL 基金会主席,Matt Caswell 负责确保 OpenSSL 使命和价值观的实现。他加入 OpenSSL 开发团队已超过 10 年,担任该库 SSL/TLS 实现的主题专家。Matt 最显著的贡献是在 OpenSSL 中实现了 TLSv1.3,以及许多其他重要功能和特性。他常驻英国,在不为 OpenSSL 贡献时,在一家大型系统集成商担任解决方案架构师。在他的wiki 页面上,他自称"有点密码学极客",对椭圆曲线密码学特别感兴趣。
Tomáš Mráz 在 2021 年作为软件开发人员加入 OpenSSL 团队,此前他长期在 Red Hat Enterprise Linux 中维护 OpenSSL 库和其他密码学包。他现任 OpenSSL 基金会的公共支持与安全管理员,并担任董事会成员。他的背景包括大量 Linux 发行版和安全包的工作经验,使他非常适合管理项目的技术和社区方面。Tomas 在监督安全响应和公共支持的同时,继续积极贡献于库的开发。
Richard Levitte 从项目一开始就加入 OpenSSL,担任开发者和维护者,几乎与项目存在时间一样长。他在 2015 年全职加入团队,主要专注于密码学库、providers(之前的 engines)、构建系统和可移植性。Richard 担任基金会董事会的财务主管,带来了关于项目从 SSLeay 起源演变的宝贵机构知识。
项目的技术实力来自其多样化的提交者团队,他们负责审查和合并代码更改。根据官方提交者列表,主要技术贡献者包括:
一位多产贡献者,经常处理密码学正确性问题。他最近的工作包括修复 ML-KEM/ML-DSA 宏拼写错误和纠正 RSA 加密/解密返回值处理,展现了对密码学细节的细致关注。
作为 Red Hat 工程师和 RHEL、CentOS 和 Fedora 发行版的 OpenSSL 维护者,Dmitry 在上游开发和企业部署之间架起桥梁。他的主要贡献是引入了用于处理不可提取对称密钥的不透明对象(EVP_SKEY)。
拥有 35 年为从初创公司到跨国企业的各种企业开发安全应用的经验,Paul 担任几个关键组件的主要开发者。他在业务咨询委员会中代表提交者,为技术决策带来宝贵的业务视角。
Oracle 员工,广泛贡献于密码学算法实现,特别专注于新密码学标准和优化。
项目基础由先驱者建立:
OpenSSL 在正式的治理结构下运作,设有两个咨询机构:
代表各种利益相关者群体,包括学术界、提交者、发行版、个人、大型企业和小型企业。这确保了业务和社区视角能够为项目方向提供信息。
专注于技术事务,包括来自相同利益相关者群体的代表,确保技术决策反映多样化的用例和要求。
最近的提交显示了项目在多个领域的活跃开发:
OpenSSL 贡献者团队特别有效的原因在于他们结合了深厚的技术专长和对实际部署挑战的理解。许多贡献者在主要科技公司(Red Hat、Oracle、Cisco、NetApp)的工作中维护 OpenSSL,确保库满足企业需求,同时保持开放和可访问。
项目的治理结构在大约 5 年前正式化,帮助团队从小型兼职个人团体扩展为有薪酬研究员、企业贡献者和活跃社区参与的结构化组织。这种演变对于在日益复杂的密码学环境中保持库的可靠性和安全性至关重要。
这些贡献者对开源原则和安全作为基本权利的承诺,推动着互联网最关键基础设施组件之一的持续改进。他们的工作确保全球数十亿用户能够获得强大、维护良好的密码学工具。
来源: https://zread.ai/openssl/openssl/9-architecture-overview
OpenSSL 是一个全面的加密工具包,为安全通信和加密操作提供了健壮的模块化架构。本概述探讨了构成 OpenSSL 项目基础的基本组织原则和结构组件。
OpenSSL 围绕三个主要的架构层构建,这些层协同工作以提供加密功能:

OpenSSL 整体架构图:展示了 libssl、libcrypto 和命令行工具之间的关系
OpenSSL 采用清晰的三层架构设计:
应用层(Application Layer)
openssl 命令提供用户友好的接口s_client、s_server 等用于协议测试协议层(Protocol Layer - libssl)
加密层(Crypto Layer - libcrypto)
crypto/ssl/apps/该架构采用分层设计,其中libssl依赖于libcrypto,从而在协议实现和加密操作之间建立了清晰的关注点分离。
架构层次说明:
现代 OpenSSL(3.0+)引入了基于提供者的架构,支持模块化加载加密实现。这种设计允许:
提供者系统在providers/下组织,包含几个关键组件:
存储库结构反映了架构的关注点分离:
crypto/- 核心加密算法和实用程序ssl/- TLS/SSL 协议实现include/- 公共头文件providers/- 加密提供者实现Configurations/- 构建和平台配置test/- 全面的测试套件fuzz/- 用于安全测试的模糊测试目标demos/- 示例应用程序和使用模式Configure- 构建配置脚本build.info- 构建元数据util/- 构建实用程序和脚本OpenSSL 采用模块化架构,其中组件松散耦合,可以独立开发、测试和维护。这在以下分离中显而易见:
ssl/)处理 TLS/SSL 状态机crypto/)提供算法实现项目使用全面的错误处理系统,包括:
OpenSSL 实现安全内存管理,包括:
该架构为不同的用例提供了几个集成点:
应用程序可以通过以下方式与 OpenSSL 集成:
apps/目录中平台特定的适配通过以下方式处理:
Configurations/中OpenSSL 架构在保持向后兼容性的同时经历了显著演进:
OpenSSL 3.0 中引入的提供者架构代表了从单体设计到模块化实现的根本性转变,通过传统提供者保持向后兼容性的同时,实现了更好的合规性、性能和可扩展性。
为了加深你对 OpenSSL 架构的理解,探索这些特定组件:
这些领域中的每一个都提供了对 OpenSSL 模块化、安全性和可扩展性架构特定方面的详细见解。
来源: https://zread.ai/openssl/openssl/10-libcrypto-cryptographic-library
libcrypto 库代表了 OpenSSL 的综合性密码学基础,提供了核心密码学原语和高级接口,为全球范围内的安全应用程序提供支持。该库作为 OpenSSL TLS/SSL 实现以及众多第三方安全应用程序的密码学引擎。
libcrypto 采用分层架构设计,旨在提供低级密码学原语和高级抽象。该库围绕**EVP (Envelope)**接口构建,该接口为各种密码学操作提供统一的 API,同时隐藏了实现复杂性。
libcrypto 架构特点:
EVP 接口:主要抽象层,为不同密码学算法提供一致的 API。位于crypto/evp/,该接口包括:
提供者架构:现代 OpenSSL 3.0+ 引入了基于提供者的架构,将算法实现与核心库分离。提供者系统允许:
核心提供者管理函数在crypto/provider.c中实现,包括OSSL_PROVIDER_load_ex()和相关操作。
该库支持全面的对称加密算法集,按算法族组织:
crypto/aes/crypto/chacha/crypto/des/crypto/camellia/公钥密码学实现在专用目录中组织:
crypto/rsa/crypto/ec/crypto/dh/crypto/dsa/消息摘要算法在各自目录中实现:
crypto/sha/(SHA-1, SHA-2, SHA-3)crypto/md5/,crypto/md4/,crypto/md2/crypto/blake2/,crypto/sm3/,crypto/whrlpool/libcrypto 提供全面的内存管理和线程安全功能:
该库包含专为密码学安全设计的专用内存分配函数:
// 安全内存分配(来自 include/openssl/crypto.h.in)
void *CRYPTO_malloc(size_t num, const char *file, int line);
void *CRYPTO_zalloc(size_t num, const char *file, int line);
void CRYPTO_free(void *ptr, const char *file, int line);
void CRYPTO_clear_free(void *ptr, size_t num, const char *file, int line);
线程同步通过 CRYPTO 锁定 API 处理:
// 线程安全操作(来自 include/openssl/crypto.h.in)
CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void);
int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock);
int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock);
int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock);
还提供原子操作用于无锁编程:
int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock);
int CRYPTO_atomic_add64(uint64_t *val, uint64_t op, uint64_t *ret, CRYPTO_RWLOCK *lock);
该库使用在crypto/init.c中实现的复杂初始化系统。OPENSSL_init_crypto()函数提供对库功能的细粒度控制:
int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
关键初始化选项包括:
OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS:跳过加载密码学错误字符串OPENSSL_INIT_LOAD_CRYPTO_STRINGS:加载密码学错误字符串OPENSSL_INIT_ADD_ALL_CIPHERS:加载所有密码算法OPENSSL_INIT_ADD_ALL_DIGESTS:加载所有摘要算法OPENSSL_INIT_NO_AUTO_CONFIG:跳过自动配置加载OpenSSL 3.0+ 引入库上下文 (OSSL_LIB_CTX) 用于隔离的密码学操作:
OSSL_LIB_CTX *OSSL_LIB_CTX_new(void);
void OSSL_LIB_CTX_free(OSSL_LIB_CTX *ctx);
libcrypto 通过 ERR 库提供全面的错误报告系统:
错误处理集成在整个库中,每个主要组件都有自己的错误代码(例如ERR_LIB_EVP,ERR_LIB_RSA)。
该库在crypto/x509/和相关目录中包含全面的 X.509 证书处理:
抽象语法表示法一 (ASN.1) 支持在crypto/asn1/中提供,支持:
libcrypto 包含多种性能优化机制:
该库实现算法缓存以避免重复初始化开销:
// EVP 接口中的算法缓存
static int evp_cipher_cache_constants(EVP_CIPHER *cipher);
libcrypto 实现了各种旁道攻击缓解措施:
通过提供者架构,libcrypto 可以在 FIPS 140-2/3 兼容模式下运行:
// 示例:使用 EVP 接口进行 AES-GCM 加密
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, key, iv);
EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len);
EVP_EncryptFinal_ex(ctx, ciphertext + len, &len);
EVP_CIPHER_CTX_free(ctx);
// 示例:SHA-256 摘要计算
EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL);
EVP_DigestUpdate(mdctx, data, data_len);
EVP_DigestFinal_ex(mdctx, digest, &digest_len);
EVP_MD_CTX_free(mdctx);
为了更深入地了解 libcrypto 的能力:
libcrypto 库代表了数十年的密码学工程,为跨平台和用例的密码学应用程序提供了强大、安全和高性能的基础。
来源: https://zread.ai/openssl/openssl/11-libssl-tls-ssl-protocol-implementation
libssl 库是 OpenSSL 对 TLS/SSL 协议的实现,为网络上的安全通信提供了核心功能。该组件处理完整的 TLS/SSL 协议栈,包括握手协商、记录层处理和密码学操作。
libssl 由多个关键架构组件组成,这些组件协同工作以实现 TLS/SSL 协议套件:
TLS/SSL 实现围绕一个精密的状态机展开,该状态机管理复杂的握手过程。状态机在statem/目录中实现,核心逻辑位于statem.c。该状态机处理客户端和服务器的握手流程,管理从初始连接建立到安全数据传输的各种协议状态转换。
状态机架构支持:
记录层是 TLS/SSL 通信的基础,负责分片、压缩、加密和传输应用数据。记录层架构在record/record.h中定义,并在record/目录的多个文件中实现。
关键记录层组件包括:
libssl 提供对多个 TLS 协议版本的全面支持:
数据报 TLS (DTLS) 通过d1_lib.c及相关文件中的专用记录层处理得到支持。DTLS 通过 UDP 等不可靠传输提供安全通信,具有以下特性:
主要的 SSL 连接对象通过ssl_lib.c中的函数进行管理。关键操作包括:
SSL_new()和SSL_CTX_new()用于建立新的 SSL 上下文libssl 与 libcrypto 库集成以执行所有密码学操作,提供:
TLS 扩展通过statem/目录中的模块化系统处理:
最新版本在quic/目录中包含实验性 QUIC 支持,实现了基于 TLS 1.3 安全性的下一代传输协议。这包括:
libssl 包含众多安全增强:
实现包含多项性能优化:
libssl 为应用程序集成提供全面的 API:
库与 OpenSSL 的 provider 系统集成以执行密码学操作:
SSL_CTX *ctx = SSL_CTX_new(TLS_client_method());
SSL *ssl = SSL_new(ctx);
SSL_set_fd(ssl, sockfd);
SSL_connect(ssl);
SSL_write(ssl, data, len);
SSL_read(ssl, buffer, sizeof(buffer));
SSL_shutdown(ssl);
SSL_CTX *ctx = SSL_CTX_new(TLS_server_method());
SSL_CTX_use_certificate_file(ctx, "cert.pem", SSL_FILETYPE_PEM);
SSL_CTX_use_PrivateKey_file(ctx, "key.pem", SSL_FILETYPE_PEM);
SSL *ssl = SSL_new(ctx);
SSL_set_fd(ssl, client_fd);
SSL_accept(ssl);
libssl 实现持续演进,包括:
希望了解完整 OpenSSL 架构的开发者,此 libssl 实现与libcrypto - Cryptographic Library协同工作,提供所有密码学原语。对最新协议开发感兴趣的读者可探索TLS 1.3 Protocol Stack获取详细实现信息。
来源: https://zread.ai/openssl/openssl/12-command-line-tool-architecture
OpenSSL 命令行工具架构代表了一个复杂的框架,通过统一界面管理加密操作。该架构展示了优雅的设计模式,实现了可扩展性、可维护性,并在数十个加密命令中提供了一致的用户体验。
命令行工具架构以基于分发的设计为核心,其中单一入口点(openssl.c)通过动态注册系统将命令路由到专门的处理器。主要组件包括:
apps/openssl.c作为主入口点和命令路由器命令行工具架构:
progs.pl 自动生成命令表架构采用代码生成方式进行命令注册。apps/progs.plPerl 脚本扫描源文件中匹配*_main(int argc, char *argv[])模式的函数,并自动生成命令注册表progs.pl#L25-L44。这种方法确保:
生成的progs.h定义了将命令名映射到其处理器的FUNCTION结构体数组progs.pl#L121-L147:
typedef struct function_st {
FUNC_TYPE type;
const char *name;
int (*func)(int argc, char *argv[]);
const OPTIONS *help;
const char *deprecated_alternative;
const char *deprecated_version;
} FUNCTION;
分发系统通过do_cmd()函数中的哈希表查找机制运行openssl.c#L460-L502。当调用命令时:
哈希表在prog_init()中初始化,该函数按字母顺序对函数排序以获得更好的帮助显示,并创建高效的查找结构openssl.c#L524-L547。
命令被分为不同的类型,这些类型决定了它们的行为和处理方式:
FT_generalgenrsa,req,x509FT_mdsha256,md5,blake2b512FT_cipheraes-256-cbc,des-ecbFT_pkeypkey,pkeyutl这种分类允许对不同命令类别进行特殊处理,例如摘要和密码的动态算法发现openssl.c#L470-L478。
架构通过三个全局 BIO 流提供标准化 I/O 处理apps.h#L50-L53:
bio_in:标准输入流bio_out:标准输出流bio_err:错误输出流这些流支持多种格式,并在所有命令中提供一致的行为。
分层配置系统支持:
app_load_config_*()系列函数处理配置加载,具有各种详细程度和错误处理策略apps.h#L69-L74。
架构融入了以安全为中心的设计元素:
安全内存功能由
OPENSSL_SEC_MEM环境变量控制,通过在受保护内存区域中分配敏感数据来防范内存转储攻击。
架构使命令添加变得简单直接:
int cmd_main(int argc, char *argv[])的函数const OPTIONS cmd_options[]结构化弃用系统允许命令的优雅演进:
progs.pl中的弃用表将旧命令映射到其现代替代方案progs.pl#L105-L119。
架构支持基于功能的命令包含:
命令行工具作为核心 OpenSSL 库的用户界面:
每个命令通常遵循:参数解析 → 上下文初始化 → 加密操作 → 结果格式化 → 清理的模式,确保所有工具间一致的资源管理。
要加深对 OpenSSL 架构的理解:
命令行工具架构展示了设计良好的分发系统如何既能为最终用户提供简便性,又能为开发者提供可扩展性,使 OpenSSL 成为加密操作的通用工具包。
来源: https://zread.ai/openssl/openssl/13-symmetric-ciphers-aes-chacha-des
OpenSSL 的对称密码实现代表了最复杂的密码工程成就之一,为全球最广泛使用的加密算法提供了高性能、安全的实现。该架构通过精心设计的抽象和平台特定优化,在可移植性、性能和安全性之间取得了平衡。
OpenSSL 通过分层架构组织对称密码,将算法接口与实现分离。核心抽象层位于 EVP(Envelope)模块中,为所有对称操作提供统一的 APIcrypto/evp/evp_lib.c。这种设计允许应用程序在无需更改代码的情况下切换算法,同时保持最佳性能。
对称密码架构:
密码实现遵循一致的模式:用于正确性和可移植性的高级 C 代码,辅以针对性能关键路径的架构特定汇编。每个算法都驻留在crypto/下的自己的目录中,并为不同平台提供专门实现。
AES(Advanced Encryption Standard)是现代对称密码学的基石。OpenSSL 的实现展示了复杂的优化技术,同时保持恒定时间执行以防止时序攻击。
crypto/aes/aes_core.c中的 AES 实现遵循标准的 Rijndael 结构,每轮包含四个主要转换:
该实现提供了两种不同的路径:用于安全关键应用的恒定时间版本和用于最大性能的基于表的版本crypto/aes/aes_core.c。
AES 密钥扩展通过KeyExpansion函数crypto/aes/aes_core.c将密码密钥转换为轮密钥。该过程因密钥大小而异:
解密密钥调度通过反转轮密钥顺序并对中间轮应用逆 MixColumns 变换从加密调度导出crypto/aes/aes_core.c。
OpenSSL 为 AES 采用多种优化策略:
恒定时间实现使用位切片技术来消除数据依赖的内存访问crypto/aes/aes_core.c。
ChaCha20 是一种现代流密码,专为高性能和安全性而设计。OpenSSL 的实现专注于向量化和并行处理能力。
crypto/chacha/chacha_enc.c中的 ChaCha20 核心函数实现了构成密码基础的四分之一轮函数:
static void chacha20_core(chacha_buf *output, const u32 input[16])
该算法使用 32 位字的 4×4 矩阵处理 64 字节块,应用 20 轮列和对角线四分之一轮操作。
主接口函数ChaCha20_ctr32crypto/chacha/chacha_enc.c实现计数器模式加密:
该实现包括 RISC-V 向量化支持,以在现代处理器上获得最佳性能crypto/chacha/chacha_enc.c。
虽然被认为已过时,但 DES(Data Encryption Standard)仍受支持以保持兼容性。该实现遵循 Feistel 网络结构,包含 16 轮 DES 函数。
OpenSSL 通过专用实现文件支持多种分组密码模式:
每种模式根据其特定要求处理初始化向量、填充和并行化。
EVP 层提供算法无关的接口,根据可用的硬件功能自动选择最佳实现。关键函数包括:
EVP_EncryptInit_ex():初始化加密上下文EVP_EncryptUpdate():处理数据块EVP_EncryptFinal_ex():完成加密EVP_Decrypt*():相应的解密函数该框架对应用程序透明地处理算法协商、密钥验证和模式特定操作。
OpenSSL 的对称密码实现包含多项安全特性:
恒定时间 AES 实现使用位切片来消除数据依赖的内存访问,这对于在共享环境中防止缓存时序攻击至关重要。
ChaCha20 的设计由于其统一的指令流和缺乏数据依赖分支,天然抵抗时序攻击,使其成为高安全性应用的理想选择。
性能在不同算法和平台间差异显著:
现代实现大量依赖硬件加速(在可用时),并回退到优化的软件实现以保持兼容性。
OpenSSL 继续发展其对称密码支持,重点关注:
模块化架构确保了新算法的无缝集成,同时保持与现有代码的向后兼容性。
要更深入地了解特定算法,请探索非对称算法 (RSA, ECDSA, DH)文档或检查哈希函数和消息摘要实现细节。
来源: https://zread.ai/openssl/openssl/14-asymmetric-algorithms-rsa-ecdsa-dh
OpenSSL 提供了三种基本非对称密码算法的全面实现,这些算法构成了现代安全通信的支柱。这些算法支持密钥交换、数字签名和加密操作,对 TLS/SSL 协议、PKI 基础设施和安全应用程序开发至关重要。
OpenSSL 中的非对称算法实现采用分层架构,将数学运算与高级密码操作分离:
非对称密码架构:
RSA (Rivest-Shamir-Adleman) 是应用最广泛的非对称算法,同时提供加密和数字签名功能。OpenSSL 的 RSA 实现支持传统的双素数密钥和现代多素数配置。
RSA 实现围绕crypto/rsa/rsa_lib.c中定义的RSA结构展开,该结构管理所有密钥组件:
OpenSSL 中的 RSA 密钥生成通过RSA_generate_key_ex()和RSA_generate_multi_prime_key()函数rsa_gen.c#L42-L77支持传统的双素数和多素数密钥。多素数实现允许最多使用 RSA_MAX_PRIME_NUM 个素数,以增强安全性和性能。
多素数 RSA 密钥可以在保持等效安全级别的同时为解密操作提供更好的性能,但需要仔细实现以避免侧信道漏洞。
OpenSSL 的 RSA 实现包含全面的安全措施:
RSA API 与 OpenSSL 的 EVP 接口无缝集成,既提供低级直接访问,也提供高级基于 EVP 的操作。像RSA_set0_key()rsa_lib.c#L376-L403这样的密钥管理函数允许安全地操作密钥组件。
椭圆曲线密码学 (ECC) 以显著更小的密钥尺寸提供与 RSA 等效的安全性,使其成为受限环境和移动应用的理想选择。
crypto/ec/ec_lib.c中的 EC 实现围绕EC_GROUP结构展开,该结构定义了椭圆曲线参数:
椭圆曲线点运算通过EC_POINT结构实现,支持:
OpenSSL 支持一套全面的标准化曲线:
EC 实现包含多项性能优化:
Diffie-Hellman (DH) 能够在不安全信道上实现安全密钥交换,是 TLS 密钥协商协议的基础。
crypto/dh/dh_lib.c中的 DH 实现通过DH结构管理密钥交换参数:
DH 密钥生成遵循标准化参数集或自定义参数:
// DH 参数设置
DH *dh = DH_new();
DH_set0_pqg(dh, p, q, g); // 设置素数、可选的 q 和生成元
DH_generate_key(dh); // 生成私钥/公钥对
OpenSSL 的 DH 实现包含多项安全特性:
始终使用标准化的 DH 参数集 (RFC 3526, RFC 7919) 或彻底验证自定义参数,以避免已知的 DH 攻击。
OpenSSL 3.0 的 provider 架构通过可插拔模块扩展这些算法:
provider 架构在保持 API 兼容性的同时,支持算法特定的优化。
为安全实现非对称算法:
OpenSSL 支持高级非对称算法特性:
OpenSSL 中的非对称算法实现为现代密码应用提供了强大、安全的基础,全面的 API 支持从基本操作到高级密码协议的所有功能。
来源: https://zread.ai/openssl/openssl/15-hash-functions-and-message-digests
OpenSSL 提供了一套全面的加密哈希函数和消息摘要算法,构成了现代加密系统的基础。本文档探讨了 OpenSSL 加密库中哈希函数的实现细节、架构和使用模式。
OpenSSL 通过分层架构实现哈希函数,将高级 API 与底层算法实现分离。哈希函数生态系统主要位于crypto/目录中,每个算法族都有专门的子目录。
哈希函数架构:
SHA(安全哈希算法)系列是 OpenSSL 中最广泛使用的哈希函数。实现集中在crypto/sha/目录中,为不同平台提供了优化版本。
SHA-1 实现遵循 FIPS 180-4 标准,并注重性能优化。核心算法在sha_local.h中使用基于宏的方法实现,支持优化和通用两种实现 [crypto/sha/sha_local.h#L59-L68]。
SHA-1 初始化使用标准化的初始哈希值:
#define INIT_DATA_h0 0x67452301UL
#define INIT_DATA_h1 0xefcdab89UL
#define INIT_DATA_h2 0x98badcfeUL
#define INIT_DATA_h3 0x10325476UL
#define INIT_DATA_h4 0xc3d2e1f0UL
压缩函数实现了 80 轮处理,包含优化的逻辑函数:
F_00_19:第 0-19 轮的 Ch 函数F_20_39:第 20-39 轮的奇偶函数F_40_59:第 40-59 轮的多数函数F_60_79:第 60-79 轮的奇偶函数 [crypto/sha/sha_local.h#L83-L86]SHA-256 实现通过不同的初始哈希值提供 SHA-256 和 SHA-224 两种变体,同时共享相同的核心算法。sha256.c中的实现包含多种优化路径:
关键常量:算法使用定义为K256[64]数组的 64 个轮常量 [crypto/sha/sha256.c#L138-L155]。
优化策略:
核心压缩函数实现了 SHA-256 逻辑函数:
#define Sigma0(x) (ROTATE((x), 30) ^ ROTATE((x), 19) ^ ROTATE((x), 10))
#define Sigma1(x) (ROTATE((x), 26) ^ ROTATE((x), 21) ^ ROTATE((x), 7))
#define Ch(x, y, z) (((x) & (y)) ^ ((~(x)) & (z)))
#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
[crypto/sha/sha256.c#L195-L212]
SHA-512 将 SHA-256 设计扩展到 64 位操作,支持 SHA-512、SHA-384、SHA-512/224 和 SHA-512/256 变体。sha512.c中的实现使用 64 位操作处理 80 轮处理。
平台特定优化:代码包含针对各种架构的广泛优化:
80 个轮常量定义为具有 64 位值的K512[80]数组 [crypto/sha/sha512.c#L342-L382]。
在 64 位平台上,SHA-512 实现可以实现比 SHA-256 更高的吞吐量,因为每轮可以处理两倍的数据,同时保持相似的计算复杂度。
SHA-3 代表了与先前 SHA 算法使用的 Merkle-Damgård 构造的不同。sha3.c中的实现遵循 NIST FIPS 202 标准。
Keccak 核心:海绵构造通过 Keccak1600 状态实现,该状态操作 64 位字的 5×5 矩阵。实现支持 SHA-3 和原始 Keccak 模式 [crypto/sha/sha3.c#L28-L43]。
关键函数:
ossl_sha3_init():使用指定的输出长度初始化 SHA-3 上下文ossl_sha3_update():将输入数据吸收到海绵状态ossl_sha3_final():从海绵状态挤压输出ossl_sha3_squeeze():XOF 模式的扩展挤压操作MD5 虽然在抗碰撞性方面已被密码学攻破,但为了兼容性仍然受到支持。实现遵循 RFC 1321 规范,具有与 SHA 算法类似的优化。
RIPEMD-160 提供了具有不同设计理念的 160 位哈希函数替代方案。实现位于crypto/ripemd/目录,在 32 位平台上提供良好的性能。
OpenSSL 哈希实现采用多种优化策略:
平台特定的汇编实现提供了显著的性能改进:
实现利用 CPU 指令集扩展:
优化的内存访问模式最小化缓存未命中并最大化吞吐量:
SHA 实现根据数据对齐使用不同的优化策略。对于小端平台上的对齐数据,使用直接内存访问,而非对齐数据则触发逐字节处理,并进行适当的字节序转换。
哈希 API 在所有算法中遵循一致的模式:
// 初始化上下文
SHA256_CTX ctx;
SHA256_Init(&ctx);
// 更新数据
SHA256_Update(&ctx, data, data_len);
// 完成并获取摘要
unsigned char digest[SHA256_DIGEST_LENGTH];
SHA256_Final(digest, &ctx);
为方便起见,OpenSSL 提供了一站式函数:
unsigned char digest[SHA256_DIGEST_LENGTH];
SHA256(data, data_len, digest);
高级 EVP 接口提供与算法无关的访问:
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
const EVP_MD *md = EVP_sha256();
EVP_DigestInit_ex(ctx, md, NULL);
EVP_DigestUpdate(ctx, data, data_len);
EVP_DigestFinal_ex(ctx, digest, &digest_len);
EVP_MD_CTX_free(ctx);
哈希函数与其他 OpenSSL 组件无缝集成:
OpenSSL 项目持续增强哈希函数实现:
要全面了解加密算法,请探索对称密码(AES、ChaCha、DES)和非对称算法(RSA、ECDSA、DH)以了解哈希函数如何与更广泛的加密系统集成。
来源: https://zread.ai/openssl/openssl/16-tls-1-3-protocol-stack
OpenSSL 中的 TLS 1.3 实现代表了 TLS 协议栈的全面重写,具有简化的握手流程、增强的安全性和改进的性能。本文档探讨了构成 TLS 1.3 协议栈的架构组件、状态机设计、加密操作和扩展处理。
OpenSSL 中的 TLS 1.3 协议栈由多个相互连接的层组成,这些层协同工作以提供安全通信。该实现采用模块化设计,将状态管理、加密操作、记录处理和扩展处理分离。
TLS 1.3 协议栈层次:
核心组件包括:
TLS 1.3 状态机在ssl/statem/目录中实现,为处理客户端和服务器的握手流程提供了统一的框架。状态机采用分层设计,具有独立的读写状态机。
主要的状态机实现在statem.c中,它协调整个握手过程source。状态机通过几个关键函数运行:
state_machine():核心状态机驱动器,协调握手进程read_state_machine():处理传入消息处理write_state_machine():管理传出消息构建状态机使用复杂的返回值系统来控制流程:
typedef enum {
MSG_PROCESS_ERROR,
MSG_PROCESS_FINISHED_READING,
MSG_PROCESS_CONTINUE_PROCESSING,
MSG_PROCESS_CONTINUE_READING
} MSG_PROCESS_RETURN;
source
客户端状态机(statem_clnt.c)实现了 TLS 1.3 客户端握手流程,具体处理:
服务器状态机(statem_srvr.c)处理服务器端握手流程:
TLS 1.3 引入了基于 HKDF 密钥派生函数的新加密架构。该实现主要位于tls13_enc.c中。
核心加密操作使用标准化的 HKDF 实现:
int tls13_hkdf_expand_ex(OSSL_LIB_CTX *libctx, const char *propq,
const EVP_MD *md,
const unsigned char *secret,
const unsigned char *label, size_t labellen,
const unsigned char *data, size_t datalen,
unsigned char *out, size_t outlen, int raise_error)
source
关键函数包括:
tls13_generate_secret()从输入密钥创建新密钥sourcetls13_derive_key()和tls13_derive_iv()生成加密密钥和 IVsourcetls13_generate_handshake_secret()创建握手特定密钥sourcetls13_generate_master_secret()派生最终主密钥sourceTLS 1.3 为不同流量阶段使用独立的密钥计划:
tls13_change_cipher_state()函数管理这些密钥状态之间的转换source。
TLS 1.3 严重依赖扩展来实现协议功能。扩展系统在extensions.c中实现,为处理所有 TLS 1.3 扩展提供了全面的框架。
每个扩展使用EXTENSION_DEFINITION结构定义:
typedef struct extensions_definition_st {
uint16_t type;
uint32_t context;
int (*init)(SSL_CONNECTION *s, unsigned int context);
int (*parse_ctos)(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx);
int (*parse_stoc)(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx);
EXT_RETURN (*construct_stoc)(SSL_CONNECTION *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx);
EXT_RETURN (*construct_ctos)(SSL_CONNECTION *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx);
int (*final)(SSL_CONNECTION *s, unsigned int context, int sent);
} EXTENSION_DEFINITION;
source
该实现包括所有强制性的 TLS 1.3 扩展:
supported_versionskey_sharepsk_kex_modespre_shared_keyearly_datacookie记录层提供 TLS 协议与底层传输之间的接口。它在ssl/record/目录中实现,主要结构在record.h中定义:
typedef struct tls_record_st {
void *rechandle;
int version;
uint8_t type;
const unsigned char *data;
unsigned char *allocdata;
size_t length;
size_t off;
uint16_t epoch;
unsigned char seq_num[SEQ_NUM_SIZE];
} TLS_RECORD;
source
记录层处理:
与以前版本相比,TLS 1.3 引入了简化的握手流程:
状态机使用复杂的转换逻辑来确保正确的消息排序和错误处理。ossl_statem_client13_read_transition()和ossl_statem_client13_write_transition()函数实现 TLS 1.3 特定的状态转换source。
TLS 1.3 包含了几个高级安全特性:
所有 TLS 1.3 密码套件通过使用 Diffie-Hellman 密钥交换(有限域或椭圆曲线)提供前向保密。该实现支持多个 DH 组和 ECDH 曲线。
该实现包括对 0-RTT 数据传输的支持,并具有适当的重放保护机制。早期数据扩展处理在扩展系统中实现source。
TLS 1.3 通过握手完成后发送的 CertificateRequest 消息支持握手后身份验证。这是通过握手后身份验证扩展实现的source。
TLS 1.3 协议栈与其他 OpenSSL 组件集成:
加密操作利用 OpenSSL provider 架构进行算法实现。这允许模块化加密 provider 支持,包括 FIPS 合规性。
TLS 1.3 作为 QUIC 协议实现的加密基础。ssl/quic/目录包含 TLS 1.3 协议栈的 QUIC 特定适配。
TLS 1.3 功能通过标准 OpenSSL SSL API 暴露,并为 TLS 1.3 特定功能提供了额外控制。
TLS 1.3 实现包括几个性能优化:
TLS 1.3 行为可以通过各种 SSL 选项和配置参数控制:
TLS 1.3 实现代表了相比以前版本的重大架构改进,状态机设计为处理扩展、加密操作和协议流的复杂交互提供了坚实的基础。
在开发使用 TLS 1.3 的应用程序时,请特别注意扩展系统,因为它构成了大多数 TLS 1.3 功能的支柱,包括密钥交换、身份验证和早期数据等高级功能。
要加深你对 OpenSSL TLS 实现的理解:
来源: https://zread.ai/openssl/openssl/17-dtls-implementation
OpenSSL 的 DTLS(Datagram Transport Layer Security,数据报传输层安全)实现在像 UDP 这样的不可靠数据报协议上提供安全通信。这个全面的实现解决了无连接传输固有的丢包、重排序和重复等独特挑战。
OpenSSL 中的 DTLS 实现建立在现有 TLS 框架的基础上,并针对数据报传输进行了特定适配。该架构由几个相互连接的组件组成:
DTLS 定义了专门的加密方法结构来处理数据报传输的独特需求。DTLSv1_enc_data和DTLSv1_2_enc_data结构(ssl/d1_lib.c)通过 DTLS 特定的标志和回调扩展了 TLS 加密方法:
DTLS 维护独立的状态结构来处理不可靠传输的复杂性:
typedef struct dtls1_state_st {
pqueue *buffered_messages; // 用于重组分片消息的队列
pqueue *sent_messages; // 用于重传的队列
unsigned int handshake_read_seq;
unsigned int handshake_write_seq;
unsigned int next_handshake_write_seq;
// 计时器和超时管理字段
} DTLS1_STATE;
初始化过程(ssl/d1_lib.c)为消息缓冲创建优先队列并设置 DTLS 特定状态。
DTLS 通过复杂的重组机制处理分片的握手消息。dtls1_reassemble_fragment函数(ssl/statem/statem_dtls.c)管理:
重组过程使用位掩码系统来跟踪消息的哪些部分已接收,能够高效检测丢失的分片并处理乱序交付。
DTLS 实现指数退避重传来处理丢包:
dtls1_start_timer、dtls1_handle_timeoutHelloVerifyRequest 机制为 DTLS 服务器提供 DoS 保护。DTLSv1_listen函数(ssl/d1_lib.c)实现无状态 cookie 验证:
DTLS 记录层(ssl/record/rec_layer_d1.c)处理:
DTLS 写入实现:
DTLS 消息流特点:
DTLS 通过ssl/statem/statem_dtls.c中的专门函数与 OpenSSL 状态机集成:
应用程序可以通过DTLS_set_timer_cb(ssl/d1_lib.c)自定义计时器行为,允许与应用程序特定事件循环集成。
DTLS 实现 MTU 路径发现以优化数据包大小:
实现使用高效的内存分配策略:
DTLS 通过以下方式提供重放保护:
多层次的 DoS 保护:
要了解更广泛的 TLS/SSL 架构,请参阅TLS 1.3 协议栈。有关密码学基础,请参考对称密码和非对称算法。
来源: https://zread.ai/openssl/openssl/18-quic-protocol-support
OpenSSL 从 3.2 版本开始提供全面的 QUIC 协议支持,并在 3.5 版本中增加了服务端功能。这种基于 UDP 的现代传输协议相比传统 TLS/DTLS 具有显著优势,包括多路复用流、降低连接建立延迟和连接迁移能力。
OpenSSL 的 QUIC 实现是与 TLS 和 DTLS 并列的一等协议,在ssl/quic/目录中拥有专门的架构。该架构采用分层设计:
QUIC 架构层次:
该实现提供了四种主要方法类型以适应不同的使用场景:
OSSL_QUIC_methodOSSL_QUIC_client_methodOSSL_QUIC_client_thread_methodOSSL_QUIC_server_methodOpenSSL 中的 QUIC 连接由QUIC_CONNECTION结构表示,它处理完整的协议状态机。连接层管理:
流实现提供阻塞和非阻塞 I/O 模型:
/* 流创建和管理 */
SSL *ssl = SSL_new(ctx);
SSL_set_bio(ssl, bio, bio);
SSL_connect(ssl);
/* 流操作 */
SSL_write_ex(ssl, data, len, &written);
SSL_read_ex(ssl, buffer, sizeof(buffer), &readbytes);
每个流通过quic_xso_st结构维护独立的状态跟踪,该结构封装了原生QUIC_STREAM对象并提供 SSL API 兼容性quic_local.h#L28-L50。
OpenSSL 提供了阻塞和非阻塞客户端示例,展示了不同的使用模式:
阻塞客户端(demos/guide/quic-client-block.c)展示了传统的套接字风格编程:
ctx = SSL_CTX_new(OSSL_QUIC_client_method());
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
ssl = SSL_new(ctx);
SSL_set_bio(ssl, bio, bio);
SSL_set_tlsext_host_name(ssl, hostname);
SSL_connect(ssl);
展示的关键功能:
非阻塞客户端(demos/guide/quic-client-non-block.c)展示了事件驱动编程,适用于高性能应用程序。
从 OpenSSL 3.5 开始,服务端 QUIC 支持使构建可扩展的 QUIC 服务成为可能。服务端实现(demos/quic/server/server.c)展示了:
ctx = SSL_CTX_new(OSSL_QUIC_server_method());
SSL_CTX_set_alpn_select_cb(ctx, select_alpn, NULL);
fd = create_socket(port);
run_quic_server(ctx, fd);
服务端实现包括:
虽然 OpenSSL 不提供原生的 HTTP/3 支持,但它提供与 HTTP/3 库的无缝集成。demos/http3/目录展示了与 nghttp3 的集成:
/* 基于 QUIC 的 HTTP/3 */
SSL *ssl = SSL_new(ctx);
SSL_set_alpn_protos(ssl, alpn_h3, sizeof(alpn_h3));
/* nghttp3 集成用于 HTTP/3 协议处理 */
对于高性能客户端应用程序,OpenSSL 提供了线程辅助模式,将协议处理卸载到后台线程:
ctx = SSL_CTX_new(OSSL_QUIC_client_thread_method());
/* 用于 I/O 处理的自动后台线程管理 */
此模式特别适用于具有以下特点的应用程序:
OpenSSL 实现了复杂的流量控制机制:
该实现支持连接迁移,允许客户端在网络更改期间保持连接:
根据你的使用场景选择合适的方法:
// 对于简单的客户端应用程序
SSL_CTX *ctx = SSL_CTX_new(OSSL_QUIC_client_method());
// 对于具有后台 I/O 的高性能客户端
SSL_CTX *ctx = SSL_CTX_new(OSSL_QUIC_client_thread_method());
// 对于服务端应用程序(OpenSSL 3.5+)
SSL_CTX *ctx = SSL_CTX_new(OSSL_QUIC_server_method());
配置应用层协议协商以进行协议选择:
/* 客户端 ALPN */
unsigned char alpn[] = {8, 'h', 't', 't', 'p', '/', '3', '.', '0'};
SSL_set_alpn_protos(ssl, alpn, sizeof(alpn));
/* 服务端 ALPN 选择 */
SSL_CTX_set_alpn_select_cb(ctx, select_alpn_callback, NULL);
OpenSSL 通过openssl s_client提供基本的 QUIC 测试功能:
openssl s_client -quic -alpn h3 -connect example.com:443
该实现包含 QLog 集成,用于详细的协议分析和调试。QLog 提供 QUIC 协议事件的结构化日志记录,用于故障排除和性能分析qlog.c。
将现有 TLS 应用程序迁移到 QUIC 时:
TLS_client_method()替换为OSSL_QUIC_client_method()有关全面的迁移指南,请参阅OpenSSL 指南和openssl-quic(7) 手册页。
QUIC 实现代表了 OpenSSL 协议支持的重大演进,与传统传输协议相比,它能够实现现代、高性能的网络应用程序,具有更低的延迟和更高的可靠性。
来源: https://zread.ai/openssl/openssl/19-fips-module-integration
OpenSSL FIPS 模块通过 provider 架构提供了符合 FIPS 140-2/140-3 验证的加密实现。本文档涵盖 FIPS provider 在 OpenSSL 生态系统中的集成、配置和操作方面的内容。
FIPS 模块作为一个可动态加载的 provider 实现,包含经过 FIPS 批准的加密算法。它以共享库的形式运行(在 Unix 上为fips.so,在 Windows 上为fips.dll),并通过 provider 接口与 OpenSSL 集成README-FIPS.md。Provider 架构允许 FIPS 模块与其他 provider 一起加载,同时保持严格的合规性边界。
要启用 FIPS 支持,必须使用enable-fips选项配置 OpenSSLREADME-FIPS.md。安装过程包含两个关键步骤:
openssl fipsinstall命令运行强制自检并生成 FIPS 模块配置文件./Configure enable-fips
make
make install_fips
# FIPS 模块安装(自动执行)
openssl fipsinstall -out /usr/local/ssl/fipsmodule.cnf -module /usr/local/lib/ossl-modules/fips.so
对于需要最新 OpenSSL 功能和经过验证的 FIPS provider 的环境,支持混合部署方法README-FIPS.md:
此策略允许安全更新,同时通过经过验证的 provider 保持 FIPS 合规性。
FIPS provider 实现了一套全面的加密算法,按功能类别组织:
FIPS provider 实现了全面的自检机制以确保操作完整性:
FIPS provider 维护一个包含四个不同状态的有限状态机providers/fips/self_test.c:
FIPS_STATE_INIT:模块加载后的初始状态FIPS_STATE_SELFTEST:自检执行阶段FIPS_STATE_RUNNING:测试成功后的运行状态FIPS_STATE_ERROR:表示测试失败的错误状态Provider 可以通过 OpenSSL 配置文件加载README-PROVIDERS.md:
openssl_conf = openssl_init
[openssl_init]
providers = provider_sect
[provider_sect]
fips = fips_sect
base = base_sect
[fips_sect]
activate = 1
应用程序可以使用 provider API 程序化加载 FIPS providerREADME-PROVIDERS.md:
#include <openssl/provider.h>
OSSL_PROVIDER *fips = OSSL_PROVIDER_load(NULL, "fips");
if (fips == NULL) {
/* 处理错误 */
}
FIPS provider 需要可靠的熵来源用于随机数生成。默认情况下,它使用操作系统的熵来源,但可以通过enable-fips-jitter配置选项配置为使用内部抖动熵来源README-FIPS.md。请注意,使用抖动熵来源需要额外的熵验证以满足 FIPS 合规性要求。
FIPS provider 实现了严格的错误处理以保持合规性:
FIPS provider 使用特定属性来识别已批准的算法:
provider=fips,fips=yesproviders/fips/fipsprov.cprovider=fips,fips=noproviders/fips/fipsprov.c这些属性允许应用程序专门请求符合 FIPS 合规性的算法实现。
将 FIPS provider 集成到应用程序时:
有关详细的使用说明和高级配置选项,请参考fips_module(7)手册页。
理解 FIPS 模块集成后,可以考虑探索:
来源: https://zread.ai/openssl/openssl/20-custom-provider-development
OpenSSL 中的自定义 provider 开发使开发者能够创建模块化的密码学算法实现,这些实现与 OpenSSL provider 架构无缝集成。本综合指南涵盖构建自定义 provider 的基本概念、实现模式和最佳实践。
OpenSSL provider 架构将密码学算法实现与核心库分离,支持算法集的模块化加载和卸载。Provider 是通过标准化接口实现特定密码学操作的动态模块。

Provider 架构设计图:展示了模块化提供者系统的工作原理
每个 provider 必须实现几个基本组件,这些组件定义了它与 OpenSSL 核心的接口:
OSSL_provider_init_fn,用于建立 provider 的存在和能力OSSL_ALGORITHM结构集合任何 provider 实现的基础都建立在 OpenSSL 核心头文件中定义的几个关键数据结构上:
// 算法定义结构
typedef struct ossl_algorithm_st {
const char *algorithm_names; // 算法名称(管道分隔)
const char *property_definition; // 属性查询字符串
const OSSL_DISPATCH *implementation; // 函数调度表
const char *algorithm_description; // 人类可读的描述
} OSSL_ALGORITHM;
// 函数调度表条目
typedef struct ossl_dispatch_st {
int function_id; // 函数标识符
void (*function)(void); // 函数指针
} OSSL_DISPATCH;
来源:providers/implementations/include/prov/implementations.h
每个 provider 必须导出一个签名为OSSL_provider_init_fn的初始化函数。此函数作为 provider 的入口点,负责:
int my_provider_init(const OSSL_CORE_HANDLE *handle,
const OSSL_DISPATCH *in,
const OSSL_DISPATCH **out,
void **provctx);
来源:providers/defltprov.c
Provider 通过OSSL_ALGORITHM结构数组注册算法。每个算法条目指定:
static const OSSL_ALGORITHM my_digests[] = {
{ "MYALG256:my-alg-256", "provider=myprovider", myalg256_functions },
{ "MYALG512:my-alg-512", "provider=myprovider", myalg512_functions },
{ NULL, NULL, NULL }
};
来源:providers/defltprov.c
每个算法实现都需要一个包含特定操作函数指针的调度表。确切的函数取决于算法类型:
摘要操作:
OSSL_FUNC_DIGEST_NEWCTX:创建新的摘要上下文OSSL_FUNC_DIGEST_INIT:初始化摘要操作OSSL_FUNC_DIGEST_UPDATE:处理数据OSSL_FUNC_DIGEST_FINAL:完成摘要OSSL_FUNC_DIGEST_FREECTX:释放摘要上下文密码操作:
OSSL_FUNC_CIPHER_NEWCTX:创建新的密码上下文OSSL_FUNC_CIPHER_ENCRYPT_INIT:初始化加密OSSL_FUNC_CIPHER_DECRYPT_INIT:初始化解密OSSL_FUNC_CIPHER_UPDATE:处理数据块OSSL_FUNC_CIPHER_FINAL:完成操作来源:providers/implementations/include/prov/implementations.h
provider 初始化遵循结构化序列:
int my_provider_init(const OSSL_CORE_HANDLE *handle,
const OSSL_DISPATCH *in,
const OSSL_DISPATCH **out,
void **provctx) {
// 存储核心句柄并解析函数
my_prov_ctx *ctx = create_provider_context();
// 设置调度表
static const OSSL_DISPATCH my_dispatch_table[] = {
{ OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))my_teardown },
,
,
{ OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))my_query },
OSSL_DISPATCH_END
};
*out = my_dispatch_table;
*provctx = ctx;
return 1;
}
来源:providers/baseprov.c
Provider 必须通过拆卸函数实现适当的清理:
static void my_teardown(void *provctx) {
my_prov_ctx *ctx = (my_prov_ctx *)provctx;
cleanup_provider_resources(ctx);
free(ctx);
}
来源:providers/baseprov.c
Provider 通过参数接口公开元数据:
static const OSSL_PARAM my_param_types[] = {
OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0),
OSSL_PARAM_DEFN(OSSL_PROV_PARAM_VERSION, OSSL_PARAM_UTF8_PTR, NULL, 0),
OSSL_PARAM_DEFN(OSSL_PROV_PARAM_BUILDINFO, OSSL_PARAM_UTF8_PTR, NULL, 0),
OSSL_PARAM_DEFN(OSSL_PROV_PARAM_STATUS, OSSL_PARAM_INTEGER, NULL, 0),
OSSL_PARAM_END
};
来源:providers/baseprov.c
核心通过query_operation函数查询 provider 的算法实现:
static const OSSL_ALGORITHM *my_query(void *provctx, int operation_id, int *no_cache) {
switch (operation_id) {
case OSSL_OP_DIGEST:
return my_digests;
case OSSL_OP_CIPHER:
return my_ciphers;
case OSSL_OP_SIGNATURE:
return my_signatures;
default:
return NULL;
}
}
来源:providers/defltprov.c
自定义 provider 必须编译为具有特定符号导出的共享库:
// 必需的符号导出
OSSL_provider_init_fn OSSL_provider_init;
Provider 可以通过配置文件或以编程方式加载:
配置文件方法:
openssl_conf = openssl_init
[openssl_init]
providers = provider_sect
[provider_sect]
myprovider = myprovider_sect
[myprovider_sect]
module = /path/to/myprovider.so
activate = 1
编程加载:
#include <openssl/provider.h>
OSSL_PROVIDER *myprov = OSSL_PROVIDER_load(NULL, "myprovider");
if (myprov == NULL) {
// 处理加载错误
}
来源:README-PROVIDERS.md
实现自定义 provider 时,始终通过保护共享资源和在并发操作之间维护适当的上下文隔离来确保线程安全。在可用时使用 OpenSSL 的线程原语。
对于生产部署,在所有 provider 函数中实现全面的参数验证和错误检查。Provider 接口应对格式错误的输入和边缘情况具有健壮性。
自定义 provider 可以通过以下方式补充现有的标准 provider:
Provider 架构允许多个 provider 共存,核心根据属性查询和可用性选择适当的实现。
有关 provider 配置和管理的更多信息,请参阅Provider 配置和管理。要了解更广泛的密码学架构,请参考架构概述。
来源: https://zread.ai/openssl/openssl/21-provider-configuration-and-management
OpenSSL 的 provider 架构代表了密码学算法在库内组织、加载和管理方式的根本性转变。该系统实现了模块化的算法实现,支持内置和第三方 provider,同时保持严格的安全边界和 FIPS 合规能力。
Provider 系统作为 OpenSSL 密码学操作的支柱,充当算法实现的容器。当通过高级 API 请求密码学操作时,会选择一个 provider 来执行实际工作。该架构提供了几个关键优势:模块化算法部署、FIPS 140-2 合规路径以及支持遗留算法隔离。
Provider 系统工作流程:
Default provider 聚合了所有标准的内置 OpenSSL 算法实现,当未指定明确的 provider 时作为主要 provider。这个内置 provider 直接编译并链接到 libcrypto 库中,无需单独的模块文件。它包含全面的算法支持,包括现代对称密码(AES、ChaCha20)、非对称算法(RSA、ECDSA、DH)、哈希函数(SHA 系列、BLAKE2)和密钥派生函数providers/defltprov.c。
Default provider 具有广泛的算法覆盖范围,包括超过 100 种密码变体、15+ 种摘要算法以及对现代密码学标准的完整支持。但是,如果另一个 provider 已经加载,它不会自动加载,在与其他 provider 一起使用时需要显式加载。
FIPS provider 包含符合 FIPS 140-2 标准的精选算法子集,专为需要法规合规性的环境而设计。该 provider 实现了严格的验证要求,与 default provider 实现相比可能表现出轻微的行为差异,以确保 FIPS 合规性providers/fips/fipsprov.c。
FIPS provider 通过属性字符串区分已批准和未批准的算法:
"provider=fips,fips=yes""provider=fips,fips=no"关键功能包括全面的自测试能力、基于 FIPS 批准状态的条件算法加载,以及与 OpenSSL 指示器回调系统的集成,用于运行时合规性监控。
Legacy provider 包含已弃用、被认为不安全或不再常用的算法。该 provider 默认情况下故意不加载,以防止意外使用弱密码学providers/legacyprov.c。
遗留算法包括:
该 provider 作为兼容性桥梁,为在迁移期间需要访问历史算法的应用程序提供服务。
Base provider 包含非密码学算法的最小子集,这些算法对于密钥序列化、反序列化和其他实用函数至关重要。当使用 FIPS provider 而不使用 default provider 时,应始终加载 base provider 以确保正确的密钥管理能力。
Null provider 是一个内置的空 provider,不包含任何算法实现。其主要目的是在应用程序希望确保独占使用显式加载的 provider 的场景下,防止自动加载 default provider,特别是在多库上下文环境中。
可以通过 OpenSSL 的配置文件系统加载和激活 provider。这种方法使使用相同 OpenSSL 安装的应用程序能够集中管理 providerREADME-PROVIDERS.md。
openssl_conf = openssl_init
[openssl_init]
providers = provider_sect
[provider_sect]
default = default_sect
fips = fips_sect
legacy = legacy_sect
[default_sect]
activate = 1
[fips_sect]
activate = 1
security_checks = 1
[legacy_sect]
activate = 1
应用程序可以使用 OSSL_PROVIDER API 以编程方式加载 provider,提供对 provider 可用性和生命周期管理的细粒度控制README-PROVIDERS.md。
#include <openssl/provider.h>
int main(void)
fips = OSSL_PROVIDER_load(NULL, "fips");
if (fips == NULL) {
/* Handle error and cleanup */
}
deflt = OSSL_PROVIDER_load(NULL, "default");
if (deflt == NULL) {
/* Handle error and cleanup */
}
/* Application logic with loaded providers */
/* Cleanup: unload providers in reverse order */
OSSL_PROVIDER_unload(deflt);
OSSL_PROVIDER_unload(fips);
OSSL_PROVIDER_unload(legacy);
return 0;
}
Provider 实现OSSL_FUNC_PROVIDER_QUERY_OPERATION函数来公开可用算法。当应用程序请求特定算法类型时,provider 管理器会查询此函数,实现基于 provider 能力的动态算法发现providers/defltprov.c。
每个算法实现都关联着属性,支持细粒度的选择和过滤。属性包括 provider 标识、FIPS 批准状态以及在多 provider 环境中指导算法选择的自定义属性。
当多个 provider 实现相同算法时,OpenSSL 使用基于以下内容的优先级系统:
FIPS provider 与 OpenSSL 的 FIPS 模块基础设施深度集成,提供:
在 provider 初始化期间和通过OSSL_FUNC_PROVIDER_SELF_TEST回调按需执行全面的自测试providers/fips/fipsprov.c。这些测试包括:
FIPS provider 实现额外的安全验证,包括:
与 OpenSSL 指示器系统的集成允许应用程序实时监控 FIPS 合规状态,支持对合规事件的动态响应providers/fips/fipsprov.c。
Provider 在库上下文中运行,为不同应用程序组件提供隔离。当未创建特定上下文时,使用默认库上下文(NULL),而自定义上下文为复杂应用程序提供 provider 隔离。
Provider 生命周期遵循明确定义的序列:
Provider 通过核心库的错误系统实现标准化错误处理,确保所有 provider 类型的一致错误报告和调试能力providers/legacyprov.c。
Provider 通过OSSL_FUNC_PROVIDER_GETTABLE_PARAMS和OSSL_FUNC_PROVIDER_GET_PARAMS函数公开配置参数,支持 provider 行为的运行时配置providers/defltprov.c。
标准参数包括:
Provider 支持基于构建时配置的广泛条件编译,允许针对特定用例和法规环境进行优化构建。功能标志控制算法包含,支持最小化部署。
Provider 在定义的安全边界内运行,防止 provider 之间的未授权访问,确保被入侵的 provider 实现不会影响其他 provider 或核心库。
Provider 系统包括内置算法验证机制,对于 FIPS 合规性尤其重要,其中算法实现必须满足严格的验证要求。
Provider 实现运行时安全措施,包括:
Provider 架构通过自动 provider 加载和算法映射保持与现有 OpenSSL 应用程序的兼容性。遗留应用程序无需代码更改即可受益于 provider 改进。
应用程序可以通过以下方式迁移到基于 provider 的配置:
该架构通过明确定义的接口支持第三方 provider 开发,实现专用密码学实现和硬件加速模块的集成。
Provider 实现算法缓存机制以减少频繁使用操作的查找开销,提高高吞吐量应用程序的性能。
高效的内存管理模式最小化分配开销,防止使用多个 provider 的长期应用程序中的内存泄漏。
Provider 实现为线程安全操作,支持多个线程对密码学操作的并发访问,同时保持数据完整性。
这种 provider 配置和管理系统为 OpenSSL 的密码学操作提供了强大、灵活的基础,支持从基本密码学任务到复杂的 FIPS 合规部署,而无需复杂的应用程序实现。
来源: https://zread.ai/openssl/openssl/22-certificate-management-and-x-509
OpenSSL 的 X.509 证书管理系统为创建、解析、验证和管理 X.509 证书及相关 PKI 结构提供了全面的框架。该实现被组织为多个模块化组件,用于处理证书生命周期管理的不同方面。
X.509 子系统围绕多个核心架构组件构建,这些组件协同工作以提供完整的证书管理功能:
X.509 子系统组件:
主要的X509结构作为 X.509 证书的核心表示。关键功能包括:
X509_new_ex()创建支持库上下文的新证书对象 [crypto/x509/x_x509.c#L155-L156]d2i_X509_AUX()和i2d_X509_AUX()处理带辅助数据的 DER 编码/解码 [crypto/x509/x_x509.c#L184-L255]X509_get0_signature()提取签名算法和值 [crypto/x509/x_x509.c#L287-L288]X509_set0_distinguishing_id()支持唯一证书标识符 [crypto/x509/x_x509.c#L301-L302]x509_vfy.c中的验证系统实现了全面的证书链验证:
X509_verify_cert()协调整个验证过程 [crypto/x509/x509_vfy.c#L306-L307]build_chain()从目标证书到信任锚构建证书链 [crypto/x509/x509_vfy.c#L3606-L3607]X509_STORE_CTX管理验证状态和配置 [crypto/x509/x509_vfy.c#L2787-L2807]证书验证步骤:
证书存储系统提供对受信任证书和 CRL 的集中管理:
X509_STORE_new()初始化新的证书存储 [crypto/x509/x509_lu.c#L200-L201]X509_LOOKUP实现各种证书检索策略 [crypto/x509/x509_lu.c#L22-L23]X509_OBJECT提供证书和 CRL 的统一处理 [crypto/x509/x509_lu.c#L612-L613]X509_STORE_add_cert()X509_STORE_add_crl()X509_STORE_CTX_get1_certs()X509_STORE_CTX_get1_crls()存储实现使用哈希表进行高效的证书查找:
ossl_x509_store_ht_get_by_name()提供按主题快速检索证书 [crypto/x509/x509_lu.c#L343-L344]obj_ht_hash()计算哈希值以实现高效存储 [crypto/x509/x509_lu.c#L193-L194]扩展系统为 X.509v3 扩展提供全面支持:
X509v3_get_ext_count()返回扩展数量 [crypto/x509/x509_v3.c#L20-L21]X509v3_get_ext_by_NID()通过 NID 查找扩展 [crypto/x509/x509_v3.c#L30-L31]X509_EXTENSION_create_by_NID()创建新扩展 [crypto/x509/x509_v3.c#L175-L176]X509v3_add_ext()X509v3_delete_ext()X509_EXTENSION_set_critical()X509_EXTENSION_get_data()名称系统处理完全支持 Unicode 的 X.501 专有名称:
X509_NAME_add_entry_by_NID()通过 NID 添加名称条目 [crypto/x509/x509name.c#L156-L157]X509_NAME_get_text_by_NID()检索文本表示 [crypto/x509/x509name.c#L19-L20]X509_NAME_ENTRY_create_by_NID()创建单个名称条目 [crypto/x509/x509name.c#L261-L262]系统提供对名称组件的细粒度控制:
X509_NAME_ENTRY_set_object()分配对象标识符 [crypto/x509/x509name.c#L306-L307]X509_NAME_ENTRY_set_data()设置条目值和类型 [crypto/x509/x509name.c#L317-L318]X509_NAME_ENTRY_get_data()提取条目数据 [crypto/x509/x509name.c#L351-L352]吊销系统支持基于 CRL 和 OCSP 的吊销检查:
get_crl_score()评估 CRL 的验证适用性 [crypto/x509/x509_vfy.c#L1629-L1630]check_crl_path()验证 CRL 颁发者链 [crypto/x509/x509_vfy.c#L1745-L1746]get_crl_delta()处理增量 CRL 更新 [crypto/x509/x509_vfy.c#L1909-L1910]在线证书状态协议支持:
check_cert_ocsp_resp()验证 OCSP 响应 [crypto/x509/x509_vfy.c#L1235-L1236]系统实现了基于时间的全面验证:
X509_cmp_current_time()比较证书有效性 [crypto/x509/x509_vfy.c#L2355-L2356]X509_cmp_timeframe()检查有效期 [crypto/x509/x509_vfy.c#L2382-L2383]X509_time_adj_ex()处理精确到天/秒的时间计算 [crypto/x509/x509_vfy.c#L2435-L2436]X509_self_signed()识别自签名证书 [crypto/x509/x509_vfy.c#L101-L102]check_key_level()验证加密密钥强度 [crypto/x509/x509_vfy.c#L4002-L4003]check_curve()验证椭圆曲线参数 [crypto/x509/x509_vfy.c#L4040-L4041]X.509 系统与其他 OpenSSL 组件集成:
X.509 验证系统通过验证参数和回调函数高度可配置,允许为不同用例定制验证行为。
现代 X.509 实现应优先使用较新的
X509_STORE_CTXAPI 而非传统函数,以获得更好的线程安全性和 Provider 集成。
要了解完整的证书管理工作流,请探索:
来源: https://zread.ai/openssl/openssl/23-key-generation-and-parameter-management
OpenSSL 为多种算法族的加密密钥生成和参数管理提供了综合框架。该系统支持传统的双素数 RSA 密钥和现代的多素数配置,以及用于 DH/DSA 算法的椭圆曲线密码学和有限域密码学。
OpenSSL 中的 RSA 密钥生成采用模块化设计,支持标准双素数和多素数密钥。主要的入口点是用于标准密钥的RSA_generate_key_ex()和用于多素数变体的RSA_generate_multi_prime_key()[crypto/rsa/rsa_gen.c#L42-L78]。
生成过程通过 RSA 方法结构委托给特定方法的实现,允许内置和基于 provider 的密钥生成:
int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb)
多素数密钥生成支持最多RSA_MAX_PRIME_NUM个素数,在素数之间自动分配位数,并包含复杂的长度验证以确保模数大小正确 [crypto/rsa/rsa_gen.c#L273-L616]。实现包括用于 FIPS 合规性的成对测试和用于安全性的恒定时间操作。
EC 密钥生成通过 EC_KEY 框架运行,采用基于方法的委托:
int EC_KEY_generate_key(EC_KEY *eckey)
if (eckey->meth->keygen != NULL)
ERR_raise(ERR_LIB_EC, EC_R_OPERATION_NOT_SUPPORTED);
return 0;
}
该系统支持标准随机密钥生成和用于后量子混合方案的 DHKEM 派生密钥 [crypto/ec/ec_key.c#L187-L416]。EC 密钥包括通过成对测试和已知答案测试进行的综合验证,以满足 FIPS 合规性要求 [crypto/ec/ec_key.c#L230-L278]。
用于 DH 和 DSA 的有限域密码学 (FFC) 参数生成遵循标准化方法,支持 FIPS 186-2 和 FIPS 186-4 算法。参数生成使用安全素数构造,并包含特定的生成器验证:
p mod 24 == 23p mod 12 == 11p mod 60 == 59在 FIPS 模式下,使用命名组而不是生成的参数,以确保符合批准的曲线标准 [crypto/dh/dh_gen.c#L95-L112]。
OpenSSL 的 OSSL_PARAM 系统为所有加密操作的参数管理提供了统一接口 [crypto/params.c]。该框架支持:
参数系统使不同算法族的密钥生成配置保持一致,同时确保类型安全并防止缓冲区溢出。
所有密钥生成操作都使用恒定时间算法和私有组件的安全内存分配。RSA 实现特别使用
BN_FLG_CONSTTIME标记私有指数和素数,以防止时序攻击 [crypto/rsa/rsa_gen.c#L128-L130]。
FIPS 合规性要求对所有生成的密钥进行成对测试,以验证数学正确性。这包括 EC 密钥的已知答案测试和 RSA 密钥的模逆验证 [crypto/ec/ec_key.c#L230-L278]。
密钥生成系统与 OpenSSL 的 provider 架构集成,允许外部实现覆盖内置算法,同时保持一致的接口。这实现了硬件加速、HSM 集成和自定义算法实现。
要全面了解加密操作,请参阅非对称算法 (RSA, ECDSA, DH)和FIPS 模块集成。
来源: https://zread.ai/openssl/openssl/24-memory-security-and-side-channel-protection
OpenSSL 实现了全面的内存安全和侧信道防护机制,以保护敏感的加密数据免受各种攻击向量的侵害。本文档探讨了核心安全特性,这些特性可防范内存泄露、时序攻击和其他侧信道漏洞。
OpenSSL 提供了一个专用的安全内存堆,专为处理敏感的加密数据而设计。安全堆实现采用伙伴分配器架构,并包含多层保护机制:
mlock()或在 Windows 上使用VirtualLock()将安全堆锁定到物理内存中,防止操作系统将敏感数据交换到磁盘crypto/mem_sec.c#L569-L584MADV_DONTDUMP显式排除核心转储中的内存crypto/mem_sec.c#L585-L588安全堆结构定义如下:
typedef struct sh_st {
char *map_result;
size_t map_size;
char *arena;
size_t arena_size;
char **freelist;
ossl_ssize_t freelist_size;
size_t minsize;
unsigned char *bittable;
unsigned char *bitmalloc;
size_t bittable_size;
} SH;
OpenSSL 为安全内存操作提供了完整的 API:
CRYPTO_secure_malloc_init()CRYPTO_secure_malloc()CRYPTO_secure_zalloc()CRYPTO_secure_free()CRYPTO_secure_clear_free()CRYPTO_secure_allocated()安全堆必须在使用前通过
CRYPTO_secure_malloc_init()初始化,该函数会设置整个安全内存基础设施,包括保护页和内存锁定。
OPENSSL_cleanse()函数是 OpenSSL 用于安全擦除内存中敏感数据的主要工具:
void OPENSSL_cleanse(void *ptr, size_t len)
该实现使用易失性函数指针来防止可能消除内存擦除操作的编译器优化crypto/mem_clr.c#L20-L26。这确保了:
OpenSSL 提供了自动清理内存的专用分配函数:
CRYPTO_clear_realloc():重新分配内存同时安全擦除原始数据crypto/mem.c#L296-L322CRYPTO_clear_free():释放内存并保证数据擦除crypto/mem.c#L334-L342CRYPTO_secure_clear_free():结合安全堆分配和显式清理虽然在内存管理文件中不直接可见,但 OpenSSL 的架构在整个加密实现中支持恒定时间操作。安全内存基础设施通过以下方式为这些保护提供基础:
伙伴分配器设计确保了可预测的内存访问模式,减少了可能被侧信道攻击利用的时序变化。分配算法维持:
在类 Unix 系统上,OpenSSL 利用高级内存保护特性:
MADV_DONTDUMP:防止安全内存出现在核心转储中mlock()与MLOCK_ONFAULT:在 Linux 系统上高效锁定内存MAP_CONCEAL:在支持的平台上的额外内存隐藏在 Windows 平台上,OpenSSL 提供等效的安全特性:
VirtualLock():锁定内存以防止分页VirtualProtect():使用PAGE_NOACCESS设置保护页OpenSSL 包含全面的内存调试功能(当未编译为 FIPS 模块时):
内存管理系统包括广泛的验证:
#define WITHIN_ARENA(p)
((char *)(p) >= sh.arena && (char *)(p) < &sh.arena[sh.arena_size])
该宏确保对安全内存的所有操作都保持在有效边界内crypto/mem_sec.c#L320-L321。
CRYPTO_secure_malloc_done()清理OPENSSL_cleanse()清理内存CRYPTO_clear_free()而非标准 free虽然安全内存提供了强大的保护,但需要考虑:
使用
CRYPTO_secure_used()监控安全内存使用情况,以避免耗尽锁定内存池,特别是在长时间运行的应用程序中。
内存安全与 OpenSSL 的加密操作深度集成。安全内存基础设施支持:
要全面了解内存安全如何与特定加密操作集成,请参阅对称密码和非对称算法文档。
这里描述的内存安全框架构成了 OpenSSL 整体安全架构的基础,确保敏感加密数据在其内存生命周期中始终受到保护。