Rust证书管理库deno_native_certs的使用:为Deno提供原生TLS/SSL证书支持
Rust证书管理库deno_native_certs的使用:为Deno提供原生TLS/SSL证书支持
该crate的目的是改善Deno在macOS上的启动时间。
在macOS上,证书是从系统钥匙串加载的。用户、管理员和系统信任设置按照Apple的文档合并在一起。Security框架是通过dlopen
动态加载的,以避免初始的dyld
开销。
在Linux和Windows上,使用了rustls-native-certs crate。
安装
安装为二进制
cargo install deno_native_certs
运行上述命令将全局安装deno_native_certs_test
二进制文件。
安装为库
在项目目录中运行以下Cargo命令:
cargo add deno_native_certs
或者将以下行添加到Cargo.toml:
deno_native_certs = "0.3.1"
使用示例
use deno_native_certs::load_native_certs;
use rustls::{Certificate, RootCertStore};
fn main() {
// 创建一个根证书存储
let mut root_store = RootCertStore::empty();
// 加载系统原生证书
let certs = load_native_certs().expect("Failed to load native certificates");
// 将证书添加到根证书存储
for cert in certs {
root_store.add(&Certificate(cert.0))
.expect("Failed to add certificate to root store");
}
// 现在root_store包含了系统的根证书,可用于TLS连接
println!("Loaded {} system certificates", root_store.len());
}
完整示例代码
下面是一个更完整的示例,演示如何使用deno_native_certs创建一个使用系统证书的TLS客户端:
use deno_native_certs::load_native_certs;
use rustls::{ClientConfig, RootCertStore};
use std::io::{Read, Write};
use std::net::TcpStream;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建根证书存储
let mut root_store = RootCertStore::empty();
// 加载系统原生证书
let certs = load_native_certs()?;
// 将证书添加到根证书存储
for cert in certs {
root_store.add(&rustls::Certificate(cert.0))?;
}
// 创建TLS客户端配置
let config = ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(root_store)
.with_no_client_auth();
// 创建TLS连接
let server_name = "example.com".try_into()?;
let mut conn = rustls::ClientConnection::new(Arc::new(config), server_name)?;
// 建立TCP连接
let mut sock = TcpStream::connect("example.com:443")?;
// 创建TLS流
let mut tls = rustls::Stream::new(&mut conn, &mut sock);
// 发送HTTP请求
tls.write_all(b"GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n")?;
// 读取响应
let mut plaintext = Vec::new();
tls.read_to_end(&mut plaintext)?;
// 打印响应
println!("{}", String::from_utf8_lossy(&plaintext));
Ok(())
}
特性说明
-
跨平台支持:
- macOS: 使用系统钥匙串加载证书
- Linux/Windows: 使用rustls-native-certs
-
性能优化:
- 在macOS上通过dlopen动态加载Security框架,减少启动时间
-
简单易用的API:
- 主要提供load_native_certs()函数
- 返回Result<Vec<Certificate>, Error>
常见问题
-
证书加载失败:
- 检查系统证书存储是否正常
- 检查是否有足够的权限访问证书存储
-
证书验证失败:
- 确保root_store正确加载了系统证书
- 检查服务器证书是否由受信任的CA签发
所有者
- Ryan Dahl
- Divy
1 回复
以下是基于提供内容整理的完整示例demo,结合了基本使用、Deno集成和reqwest的高级用法:
// 完整示例:使用deno_native_certs进行HTTPS请求
use deno_core::plugin_api::{Interface, Op, ZeroCopyBuf};
use deno_native_certs::load_native_certs;
use reqwest::ClientBuilder;
use rustls::RootCertStore;
use std::sync::Arc;
use tokio::net::TcpStream;
use tokio_rustls::TlsConnector;
// 1. 基本证书加载示例
fn load_system_certificates() {
let mut root_store = RootCertStore::empty();
load_native_certs(&mut root_store).expect("加载系统证书失败");
println!("成功加载 {} 个系统根证书", root_store.roots.len());
}
// 2. Deno插件集成
#[no_mangle]
pub fn deno_plugin_init(interface: &mut dyn Interface) {
interface.register_op("loadNativeCerts", op_load_native_certs);
}
fn op_load_native_certs(
_interface: &mut dyn Interface,
_zero_copy: &mut [ZeroCopyBuf],
) -> Op {
let mut root_store = RootCertStore::empty();
match load_native_certs(&mut root_store) {
Ok(_) => Op::Sync(Box::new(root_store.roots.len())),
Err(e) => Op::Sync(Box::new(format!("错误: {}", e))),
}
}
// 3. 使用reqwest进行安全请求
async fn secure_http_request(url: &str) -> Result<(), Box<dyn std::error::Error>> {
let mut root_store = RootCertStore::empty();
load_native_certs(&mut root_store)?;
let client = ClientBuilder::new()
.use_preconfigured_tls(root_store)
.build()?;
let response = client.get(url).send().await?;
println!("请求状态: {}", response.status());
println!("响应头: {:?}", response.headers());
Ok(())
}
// 4. 高级用法:使用tokio-rustls建立安全连接
async fn tls_connect(host: &str, port: u16) -> Result<(), Box<dyn std::error::Error>> {
let mut root_store = RootCertStore::empty();
load_native_certs(&mut root_store)?;
let config = rustls::ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(root_store)
.with_no_client_auth();
let connector = TlsConnector::from(Arc::new(config));
let stream = TcpStream::connect((host, port)).await?;
let domain = rustls::ServerName::try_from(host)?;
let mut tls_stream = connector.connect(domain, stream).await?;
// 这里可以添加TLS流的具体读写操作
println!("成功建立TLS连接到 {}:{}", host, port);
Ok(())
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 演示基本功能
load_system_certificates();
// 执行安全HTTP请求
secure_http_request("https://example.com").await?;
// 建立TLS连接
tls_connect("example.com", 443).await?;
Ok(())
}
这个完整示例展示了:
- 基本证书加载功能
- 如何集成到Deno运行时作为插件
- 结合reqwest进行安全HTTPS请求
- 使用tokio-rustls建立底层TLS连接
使用前请确保在Cargo.toml中添加以下依赖:
[dependencies]
deno_native_certs = "0.6"
deno_core = "0.142" # 仅当需要Deno集成时
reqwest = { version = "0.11", features = ["rustls-tls"] }
tokio = { version = "1.0", features = ["full"] }
tokio-rustls = "0.23"
rustls = "0.20"