Cryptology Academy · 课时

OpenSSL API:核心结构与常见陷阱

掌握 EVP API 和 BIO 抽象,并了解最常见的 OpenSSL API 误用模式。

第 2 / 4 课13 个步骤

OpenSSL API:核心结构与常见陷阱 是 CoddyKit 上的免费 Cryptology Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Cryptology Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Cryptology Academy 课程共包含 4 节课。

EVP:高级接口

EVP(封装)接口是 OpenSSL 用于密码学操作的高级接口,也是应用程序代码应使用的正确接口。它通过统一的接口隐藏特定于算法的细节,自动支持引擎和提供程序的硬件加速,并正确处理填充和模式细节。现代版本的 OpenSSL 已弃用较低级的特定算法接口,应避免使用这些接口。

用于对称加密的 EVP_CIPHER_CTX

OpenSSL 中的对称加密使用 EVP_CIPHER_CTX 上下文对象。操作顺序为:使用 EVP_CIPHER_CTX_new 分配上下文,使用 EVP_EncryptInit_ex 以密码算法和密钥进行初始化,反复使用 EVP_EncryptUpdate 处理数据,使用 EVP_EncryptFinal_ex 刷新最后一个分组并获取剩余输出,最后使用 EVP_CIPHER_CTX_free 释放内存。跳过 EncryptFinal_ex 是一种常见错误,会导致输出被截断。

用于哈希的 EVP_MD_CTX

消息摘要计算同样使用 EVP_MD_CTX:使用 EVP_MD_CTX_new,使用算法调用 EVP_DigestInit_ex(例如 EVP_sha256()、EVP_sha3_256() 等),使用 EVP_DigestUpdate 处理数据块,并使用 EVP_DigestFinal_ex 获取哈希值。HMAC 操作使用独立的 HMAC_CTX,或使用较新的 EVP_MAC 接口。EVP 抽象使得只需更改一次函数调用即可替换哈希算法。

用于非对称密钥的 EVP_PKEY

EVP_PKEY 是 OpenSSL 中统一的非对称密钥对象,通过单一接口支持 RSA、ECDSA、Ed25519、DH 和其他算法。密钥可以通过 PEM 或 DER 文件和 PEM_read_PrivateKey、PEM_read_PUBKEY 创建,也可以使用 EVP_PKEY_keygen 生成。EVP_PKEY_sign 和 EVP_PKEY_verify 使用相同的函数调用执行任意密钥类型的签名和验证。

用于输入/输出的 BIO 抽象

BIO(基本输入/输出)是 OpenSSL 的输入/输出抽象层,允许通过一系列 BIO 对象读写受 TLS 保护的数据或原始数据。一个 BIO 链可能是:将 BIO_new_ssl(TLS 层)连接到 BIO_new_connect(TCP 连接)。写入 SSL BIO 会自动加密并发送数据;读取操作会解密接收到的数据。BIO 对象支持文件、套接字、内存缓冲区和过滤器(Base64、缓冲)。

SSL_CTX 与 SSL 对象

OpenSSL 中的 TLS 连接使用两个对象:SSL_CTX(上下文)存储共享配置,包括证书、私钥、CA 证书包、协议版本限制和密码算法列表。SSL 表示从该上下文派生出的单个连接。每个应用程序创建一个 SSL_CTX,然后为每个连接从中创建 SSL 对象。SSL_read 和 SSL_write 传输明文;OpenSSL 会在内部处理所有 TLS 分帧和加密工作。

关键陷阱:忽略返回值

OpenSSL 中最危险的错误是忽略返回值。EVP_EncryptFinal_ex、SSL_read 和 SSL_write 都会通过返回负值或零来表示错误。在未检查 SSL_get_error 的情况下循环调用 SSL_read,可能导致无限循环或漏掉错误。任何可能失败的 OpenSSL 函数都必须检查其返回值;失败往往表示与安全相关的情况,例如握手失败或证书验证错误。

陷阱:不检查 SSL_get_error

SSL_read 和 SSL_write 可能返回 SSL_ERROR_WANT_READ 或 SSL_ERROR_WANT_WRITE,表示应在等待输入/输出完成后重试操作。这些并不是真正的错误,而是非阻塞输入/输出通知。不调用 SSL_get_error 并正确判断这两种情况的代码,要么会进行忙等待循环,要么会错误地将这些情况当作错误处理。始终使用 SSL_get_error 来解释 TLS 输入/输出操作的负返回值。

已弃用的低级接口

OpenSSL 包含许多不应出现在新代码中的已弃用低级函数:直接调用 DES_encrypt1、绕过 EVP 接口直接使用 SHA1 或 MD5 哈希函数、使用 RSA_private_encrypt 而不是 EVP_PKEY_sign,以及使用 AES_encrypt(未提供认证的 AES ECB)。这些接口会绕过安全检查、使用已弃用的算法,或者本身就不如对应的 EVP 接口安全。编译器警告通常会标记已弃用接口的使用。

OpenSSL 代码中的内存泄漏

OpenSSL 使用显式内存管理;每个已分配的对象都必须显式释放。常见的内存泄漏包括:加密后忘记调用 EVP_CIPHER_CTX_free、关闭连接后未调用 SSL_free,或证书验证后未调用 X509_free。在长期运行的服务器中,这些泄漏会逐渐耗尽内存。开发期间可以使用 valgrind 或 AddressSanitizer 等工具检测 OpenSSL 内存泄漏。

OpenSSL 3.0 提供程序模型

OpenSSL 3.0 引入了提供程序模型,用于取代较早的 ENGINE 硬件加速接口。提供程序是实现密码学算法的可加载模块:默认提供程序(软件)、传统提供程序(较旧算法)、FIPS 提供程序(通过 FIPS 140-2 验证)以及面向硬件安全模块的第三方提供程序。FIPS 提供程序会将可用算法限制为 FIPS 140-2 批准的算法,从而在不修改应用程序代码的情况下启用合规运行。

EVP 接口的重要性

为什么优先使用 OpenSSL EVP 接口,而不是特定于算法的低级接口?

OpenSSL 接口回顾

OpenSSL 接口回顾:始终使用 EVP 高级接口;使用 EVP_CIPHER_CTX 执行对称操作,使用 EVP_MD_CTX 进行哈希,使用 EVP_PKEY 处理非对称密钥;使用 BIO 链实现输入/输出抽象;使用 SSL_CTX 和 SSL 处理 TLS 连接;始终检查返回值并调用 SSL_get_error;释放所有已分配的对象以防止内存泄漏;避免使用已弃用的低级函数;使用 OpenSSL 3.0 提供程序实现 FIPS 合规或硬件加速。

免费开始

用 AI 导师学习 Cryptology Academy — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
67
课程
261

常见问题解答

「OpenSSL API:核心结构与常见陷阱」课时是免费的吗?

是的 — 「OpenSSL API:核心结构与常见陷阱」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Cryptology Academy 课程的其余内容,请升级到 CoddyKit PRO。 Cryptology Academy 课程共包含 4 节课。

「OpenSSL API:核心结构与常见陷阱」这节课中我会学到什么?

掌握 EVP API 和 BIO 抽象,并了解最常见的 OpenSSL API 误用模式。 你通过在浏览器中直接运行的动手代码来练习 Cryptology Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Cryptology Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Cryptology Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「OpenSSL API:核心结构与常见陷阱」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Cryptology Academy 课中编写并运行代码吗?

能。每节 Cryptology Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. libsodium:防误用密码学库
  2. OpenSSL API:核心结构与常见陷阱
  3. Google Tink:安全的高级密码学
  4. 审计与选择密码学依赖
← 返回 Cryptology Academy