mattrobenolt/ztls

GitHub: mattrobenolt/ztls

一个用 Zig 实现的 Sans-I/O TLS 1.3 状态机库,不接管 I/O 和内存分配,让调用者完全掌控传输模型与缓冲区。

Stars: 4 | Forks: 0

ztls — Sans-I/O TLS 1.3 in Zig

ztls 是一个不进行任何 I/O 操作的 TLS 1.3 库。你只需将在线路上读取到的字节喂给它;它会交还能让你写回的字节。套接字、事件循环、缓冲区全由你掌控。ztls 只负责处理协议。 它处于 pre-alpha 阶段。API 可能随时发生颠覆性变化。在基于它进行构建之前,请先阅读 [`docs/USAGE.md`](docs/USAGE.md)。 ## 为什么采用这种方式 大多数 TLS 库会接管套接字,这意味着它们也会控制你的 I/O 模型 —— 比如阻塞式调用、它们自己的异步运行时,或是特定形状的回调。ztls 完全不涉及这些。它纯粹是一个状态机:字节输入,字节输出。你可以通过阻塞式读取、epoll、io_uring 或内存管道来驱动它。示例中包含了这四种方式。 该状态机也从不调用分配器。由你提供缓冲区,它使用这些缓冲区,这就是全部的内存管理机制。没有任何东西被隐藏在堆上。需要明确指出的一点是:底层的基础加密操作被委托给了 libcrypto 后端(目前是 OpenSSL,接下来是 AWS-LC),并且 OpenSSL 在初始化及其内部例程中会进行内存分配。我们对此毫不隐瞒。但 ztls 自身的代码 —— 解析、组帧、记录序列化 —— 绝不进行任何内存分配。 其适用范围被刻意收窄。仅支持在 Linux 和 macOS 上运行的 TLS 1.3。没有会被降级攻击的 1.2 回退机制,没有 DTLS,也没有 Windows 移植层。这意味着代码量更少,攻击面也更小。 它使用 Zig 编写,因此在热路径中没有分配器操作,我们自身的源码中也没有 C 代码。AEAD、密钥交换和签名均来自 libcrypto;ztls 负责处理封装在它们外部的协议。 ## 性能 速度是 ztls 诞生的理由,因此这里展示其实际表现。 在内存级应用层数据基准测试中,在我们测试过的所有密码套件和数据大小下,ztls 的表现均优于 OpenSSL 的 libssl。与 rustls 相比则互有胜负。ztls 在 AES-GCM 上胜出。但在处理小型 ChaCha20-Poly1305 记录时落败,因为 rustls 的 ring 后端就是比 OpenSSL 的 EVP ChaCha 路径更快。代码库中也包含了那个表现落后的测试项,并附有解释原因的反汇编代码。 以下是来自 [`docs/research/perf/20260705-194022-ec2-c7i-2xlarge/`](docs/research/perf/20260705-194022-ec2-c7i-2xlarge/) 抓取结果中,使用 1350 字节记录的 AES-128-GCM 乒乓测试项(git rev `89c869e`,Zig 0.15.2 ReleaseFast,原生 CPU,`--count 5`): | 实现 | ns/op | 对比 ztls | |---|---:|---:| | ztls | 786 | — | | rustls | 1384 | +76% | | OpenSSL libssl | 1845 | +135% | 性能计数器也证实了这一点。在该测试项中,ztls 每次操作消耗的周期、指令和分支均少于任何竞争对手([`docs/research/perf/20260705-215953-ec2-c7i-2xlarge-row-perf/`](docs/research/perf/20260705-215953-ec2-c7i-2xlarge-row-perf/)),因此这绝非时钟计时上的偶然。 接下来是注意事项,因为诚实与不诚实的基准测试往往就在此处分道扬镳: - 两台 x86_64 EC2 实例。这并不能代表所有硬件矩阵,而且目前还没有重复测试或阈值策略。请将这些视作单纯的测量结果,而非营销噱头。 - rustls 的测试工具计时方式为批量执行;而 ztls 和 libssl 的则为单次迭代。测量形态并不完全相同。 [`docs/research/PERFORMANCE.md`](docs/research/PERFORMANCE.md) 提供了逐行对比的等效方法。 - 完整握手测试项并不是一场公平的较量。ztls 会验证服务器的 CertificateVerify 签名;而 rustls 和 libssl 的测试端点则不会。我们将其单独列出,绝不将其引用为直接对比的数据。 随着新结果的产生,此处的数据会被相应替换。 ## 从这里开始 阅读 [`docs/USAGE.md`](docs/USAGE.md) 获取 API 指南。如果你更倾向于阅读代码,可以从在 CI 中运行的示例开始: - [`examples/in_memory_handshake.zig`](examples/in_memory_handshake.zig) —— 双端处于同一进程中,无套接字。 - [`examples/tcp_loopback.zig`](examples/tcp_loopback.zig) —— 客户端与服务器通过 `std.net.Stream` 环回进行交互。 - [`examples/epoll_pingpong.zig`](examples/epoll_pingpong.zig) —— 非阻塞式 Linux epoll 乒乓测试。 - [`examples/iouring_pingpong.zig`](examples/iouring_pingpong.zig) —— Linux io_uring 乒乓测试。 在 devshell 中运行它们: ``` nix develop .#openssl just examples-ci ``` `nix develop .#aws-lc` 会选择 AWS-LC shell 用于后端开发。OpenSSL 是默认的 devshell,也是默认的 `-Dcrypto-backend`。 ## 支持范围 受支持的功能路径为:基于调用者所拥有缓冲区的服务器认证 TLS 1.3 1-RTT。ztls 负责协议状态、记录组帧、加密、记录哈希、警报和密钥更新。由你掌控传输 I/O、缓冲区和驱动循环。 - 仅限 TLS 1.3。TLS 1.2、DTLS 和 Windows 超出范围。 - 密码套件:`TLS_AES_128_GCM_SHA256`、`TLS_AES_256_GCM_SHA384` 和 `TLS_CHACHA20_POLY1305_SHA256`。 - 示例使用 X25519。为了进行合规性测试,存在服务器端 P-256 ECDHE。更广泛的 named-group 和提供商相关工作由 [#6](https://github.com/mattrobenolt/ztls/issues/6) 跟踪。 - 服务器证书认证可正常工作。客户端证书认证由 [#4](https://github.com/mattrobenolt/ztls/issues/4) 跟踪。 - PSK/会话恢复为 [#2](https://github.com/mattrobenolt/ztls/issues/2), 0-RTT 为 [#3](https://github.com/mattrobenolt/ztls/issues/3), HelloRetryRequest 重试为 [#1](https://github.com/mattrobenolt/ztls/issues/1)。 ## 全新项目 使用 Zig 0.15.2 或更高版本。ztls 通过 `pkg-config` 链接 libcrypto 系列提供程序;devshell 默认提供 OpenSSL。 ``` mkdir hello-ztls cd hello-ztls zig init ``` 将 ztls 添加到生成的 `build.zig.zon` 中。保留 `zig init` 生成的指纹;依赖路径是相对于你的项目根目录的。 ``` .dependencies = .{ .ztls = .{ .path = "../ztls" }, }, ``` 在 `build.zig` 中将模块接入你的可执行文件: ``` const ztls_dep = b.dependency("ztls", .{ .target = target, .optimize = optimize, }); const exe_mod = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, .imports = &.{.{ .name = "ztls", .module = ztls_dep.module("ztls") }}, }); const exe = b.addExecutable(.{ .name = "hello-ztls", .root_module = exe_mod }); ``` 现在,你可以从 `src/main.zig` 中使用 `@import("ztls")` 了。更详尽的设置说明请见 [`docs/USAGE.md`](docs/USAGE.md)。 ## 项目状态 [`PRODUCTION_READINESS.md`](PRODUCTION_READINESS.md) 记录了实际已完成的工作以及“完成”的具体定义。本 README 旨在向你说明 ztls 是什么;它不对项目状态做出任何承诺。设计说明、威胁模型以及性能证据均存放在 [`docs/research/`](docs/research/) 目录下。
标签:Sans-I/O, TLS 1.3, Zig, 内核驱动, 密码学, 手动系统调用, 状态机, 网络协议