9 个版本 (4 个重大更新)
| 0.7.1 | 2023 年 9 月 20 日 |
|---|---|
| 0.6.3 | 2023 年 9 月 7 日 |
| 0.5.2 | 2023 年 9 月 5 日 |
| 0.3.5 | 2023 年 8 月 31 日 |
| 0.2.1 | 2023 年 8 月 24 日 |
#8 in #path-finding
每月 55 次下载
215KB
1.5K SLoC
X509 Path Finder
X509 Path Finder 是一个 深度优先搜索 证书路径验证器。

概要
X509 Path Finder 受到 RFC 4158 的启发
现在许多 PKI 正在使用复杂的结构... 而不是简单的层次结构。此外,一些企业正在逐渐从包含许多信任锚点的信任列表转向一个具有一个信任锚点和许多交叉认证关系的基础设施...。本文档建议使用一种有效的一般方法来构建路径,该方法涉及深度优先树遍历。
X509 Path Finder 否认单一证书 "链" 的概念。相反,它搜索无限中的第一个匹配项。一旦找到可以验证的路径,搜索就会停止,并将路径返回给调用者。
路径搜索的复杂性受到三个因素的影响
- 预加载到其本地存储中的证书数量
- 它可以通过遵循 AIA URL 查找并下载的证书数量
- 任意时间限制
在评估路径候选以进行验证时,X509 Path Finder 是实现无关的。一旦找到已终止的路径,它就会将其呈现给后端权威机构进行验证。如果权威机构验证了路径,则搜索停止并将路径返回。如果路径被拒绝,则搜索继续。
X509 Path Finder 提供了两个 PathValidator 实现
- DefaultPathValidator - 使用 rustls-webpki 实现,默认可用。
- OpenSSLPathValidator - 使用 Rust OpenSSL 实现,可通过
openssl功能标志获得
警告
实现 PathValidator 本身很简单,但安全的 X509 路径验证 并不是。鼓励工程师使用受信任的 X509 路径验证器作为其 PathValidator 实现的基础,并在其上堆叠业务逻辑。
用法
默认情况下,提供的 DefaultPathValidator 验证器可用。
[dependencies]
x509_path_finder = { version = "*"] }
启用 openssl 功能以访问提供的 OpenSSLPathValidator 验证器。
[dependencies]
x509_path_finder = { version = "*", features = ["openssl"] }
示例
use webpki::{KeyUsage, TrustAnchor};
use std::sync::Arc;
use std::time::Duration;
use x509_path_finder::provided::validator::default::DefaultPathValidator;
use x509_path_finder::{X509PathFinder, X509PathFinderConfiguration};
async fn test_find(
root: Vec<u8>,
ic: Vec<Arc<x509_path_finder::Certificate>>,
ee: x509_path_finder::Certificate,
) -> Result<(), x509_path_finder::X509PathFinderError> {
// instantiate default validator
let root = TrustAnchor::try_from_cert_der(root.as_slice()).unwrap();
let algorithms = &[&webpki::ECDSA_P256_SHA256];
let validator = DefaultPathValidator::new(algorithms, vec![root], KeyUsage::client_auth(), &[]);
// instantiate the finder
let mut search = X509PathFinder::new(X509PathFinderConfiguration {
limit: Duration::default(),
aia: None,
validator,
certificates: ic,
});
// execute the search
let found = search.find(ee).await?.found.unwrap();
// path has two certificates
assert_eq!(2, found.path.len());
// Found is also an iterator over path
assert_eq!(2, found.into_iter().count());
Ok(())
}
配置
使用 X509PathFinderConfiguration 结构配置 X509 路径构建器,该结构具有以下字段
limit: 限制路径搜索的执行时间。实际限制将是 N * HTTP 超时。有关设置 HTTP 连接超时的信息,请参阅reqwest::ClientBuilder::timeout。aia: 可选的x509_client::X509ClientConfiguration以启用 权威信息访问 扩展。validator:PathValidator实现方案certificates: 用于路径查找的附加中间、桥接和交叉签名证书。这些证书首先考虑作为路径候选,并按顺序尝试。
资源管理
由于 X509 路径构建器可以从网络上消耗 AIA URL,对 X509PathFinder::find 的调用理论上可以无限期运行,或被强制下载大量数据。可以通过以下配置设置管理资源消耗
- 将
limit持续时间设置为非零值 - 将
reqwest::ClientBuilder::timeout设置为更激进的值 - 通过将
x509_client::X509ClientConfiguration::limit设置为非零值限制证书下载大小 - 禁用 AIA
查找路径
调用 X509PathFinder::find 以查找路径。提供目标端实体 Certificate 以开始搜索。搜索将逆向工作到根证书。
返回的 Report 包含以下字段
found: 在路径查找成功时,包含Foundduration: 路径搜索的持续时间store: 未用于发现路径的缓存的Certificate集合failures:由PathValidator实现报告的任何验证错误都保存在ValidationFailure中。
找到
Found 结构体包含以下字段
- path - 发现的路径,一个
Certificate的 vec。路径包括目标证书。根据 RFC 5246,路径是从目标开始,向信任锚方向排序的。 - origin - 路径的
CertificateOrigin
Found 还是一个遍历 path 成员引用的迭代器。
CertificateOrigin
CertificateOrigin 是一个枚举,描述了每个证书的来源。可以是以下之一
Target:调用X509PathFinder::find时的初始证书。Store:证书在存储中找到Url:证书从 URL(AIA)下载
ValidateFailure
ValidationFailure 存储任何验证错误。即使在最终找到有效的证书路径的情况下,也可能发生验证错误。ValidateFailure 包含以下字段
path- 验证错误发生的Certificate的路径 vecorigin:验证错误发生的CertificateOriginreason:失败的可读原因
ValidationFailure 还是一个遍历 path 成员引用的迭代器。
API
可以实现 X509 PathValidator API 以使用不同的后端权威机构验证证书路径并添加业务逻辑,特别是 策略 约束。
实现
- DefaultPathValidator- 使用 rustls-webpki 验证路径
- OpenSSLPathValidator- 使用 OpenSSL 验证路径
TODO
按优先级排序
- 更深入的集成测试
- 基准测试
- 在构建路径时缓存发行者 <-> 主题映射
- 在摄入时忽略无效证书,而不是等待
PathValidator拒绝整个路径候选者 - 并行化 AIA 下载
- 加权路径决策
依赖项
~12–26MB
~500K SLoC