Rust中使用rcgen生成自签名证书
rcgen 是一个纯 Rust 实现的 X.509 证书生成库,支持自签名证书、CA 证书和 CSR(证书签名请求)。
添加依赖
cargo add rcgen@~0.14.8
cargo add time # 时间库,辅助设置有效期
cargo add p12-keystore@~0.3.1 # 导出pfx格式文件
主要类型
| 类型 | 说明 |
|---|---|
CertificateParams |
证书参数配置(域名、有效期、密钥用途等) |
KeyPair |
密钥对,可序列化为 PEM/DER |
DistinguishedName |
证书主题信息(CN, O, OU 等) |
IsCa |
标记该证书是否为 CA 证书 |
生成自签名证书
use std::fs;
use p12_keystore::{Certificate, KeyStore, KeyStoreEntry, PrivateKey, PrivateKeyChain};
use rcgen::{CertificateParams, DistinguishedName, DnType, ExtendedKeyUsagePurpose, KeyPair, KeyUsagePurpose, SanType, SerialNumber};
use time::{OffsetDateTime, Duration};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. 配置证书参数
let mut params = CertificateParams::default();
// 设置 SAN 扩展(Subject Alternative Name)
params.subject_alt_names = vec![
SanType::DnsName("example.com".parse()?),
SanType::DnsName("localhost".parse()?),
SanType::IpAddress("127.0.0.1".parse()?),
];
// 另一种方法,实例化证书参数并设置SAN
let mut params = CertificateParams::new(vec![
"example.com".to_string(),
"localhost".to_string(),
"127.0.0.1".to_string()
])?;
// 设置证书主体信息 (Subject DN)
let mut dn = DistinguishedName::new();
dn.push(DnType::CommonName, "example.com");
dn.push(DnType::OrganizationName, "My Company");
dn.push(DnType::OrganizationalUnitName, "Engineering Department");
dn.push(DnType::CountryName, "US");
dn.push(DnType::StateOrProvinceName, "California");
dn.push(DnType::LocalityName, "San Francisco");
params.distinguished_name = dn;
// 设置证书有效期
// 生效时间:1 小时前
params.not_before = OffsetDateTime::now_utc() - Duration::hours(1);
// 过期时间:365 天后
params.not_after = OffsetDateTime::now_utc() + Duration::days(365);
// 设置密钥用法
params.key_usages = vec![
KeyUsagePurpose::DigitalSignature,
KeyUsagePurpose::KeyEncipherment,
];
// 设置扩展密钥用法(TLS 服务端/客户端认证)
params.extended_key_usages = vec![
ExtendedKeyUsagePurpose::ServerAuth,
ExtendedKeyUsagePurpose::ClientAuth,
];
// 自定义序列号(可选)
// 从数字创建
params.serial_number = Some(SerialNumber::from(12345u64));
// 从大数创建
params.serial_number = Some(SerialNumber::from_slice(
&[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC]
));
// 2. 生成密钥对
// rcgen 默认使用合适强度的算法生成密钥对
let key_pair = KeyPair::generate()?;
// 自定义密钥算法
// ECDSA P-256 密钥(默认算法)
let ecdsa_key_pair = KeyPair::generate_for(&rcgen::PKCS_ECDSA_P256_SHA256)?;
// ECDSA P-384 密钥
let ecdsa384_key_pair = KeyPair::generate_for(&rcgen::PKCS_ECDSA_P384_SHA384)?;
// Ed25519 密钥(推荐用于高性能场景)
let ed25519_key_pair = KeyPair::generate_for(&rcgen::PKCS_ED25519)?;
// RSA 2048 密钥(兼容性最好)
let rsa_key_pair = KeyPair::generate_for(&rcgen::PKCS_RSA_SHA256)?;
// 3. 生成自签名证书
let cert = params.self_signed(&key_pair)?;
// 4. 导出为不同格式
// PEM 格式(文本格式)
let cert_pem = cert.pem();
let key_pem = key_pair.serialize_pem();
// DER 格式(二进制格式)
let cert_der = cert.der();
let key_der = key_pair.serialize_der();
// 使用 p12-keystore 将其打包为 PFX/PKCS12 格式
let p12_cert = Certificate::from_der(cert_der)?;
let p12_key = PrivateKey::from_der(&key_der)?;
let chain = PrivateKeyChain::new(b"key-id".to_vec(), p12_key, vec![p12_cert]);
let pfx_password = "password123"; // PFX 文件的加密密码
let friendly_name = "my-dev-cert"; // 证书别名/友好名称
// 实例化一个 KeyStore
let mut keystore = KeyStore::new();
keystore.add_entry(friendly_name, KeyStoreEntry::PrivateKeyChain(chain));
let pfx_bytes = keystore.writer(pfx_password).write()?;
// 将生成的二进制流写入本地的 .pfx 文件
fs::write("cert_bundle.pfx", pfx_bytes)?;
println!("成功生成自签名证书");
Ok(())
}
生成 CA 证书并签发服务端证书
这是生产环境常见的两层级证书链:
use rcgen::{BasicConstraints, CertificateParams, IsCa, KeyPair, KeyUsagePurpose};
// 1. 创建 CA 根证书
let ca_key = KeyPair::generate()?;
let mut ca_params = CertificateParams::new(vec!["My Root CA".to_string()])?;
ca_params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained); // 无限制 CA
ca_params.key_usages = vec![
KeyUsagePurpose::KeyCertSign,
KeyUsagePurpose::CrlSign,
];
let ca_cert = ca_params.self_signed(&ca_key)?;
// 2. 创建服务端证书(由 CA 签发)
let server_key = KeyPair::generate()?;
let mut server_params = CertificateParams::new(vec![
"myserver.com".to_string(),
"localhost".to_string(),
])?;
server_params.is_ca = IsCa::NoCa; // 非 CA 证书
// 3. CA 签发服务端证书
let server_cert = server_params.signed_by(&server_key, &ca_cert, &ca_key)?;
// 4. 导出证书链
fs::write("ca_cert.pem", ca_cert.pem())?;
fs::write("ca_key.pem", ca_key.serialize_pem())?;
fs::write("server_cert.pem", server_cert.pem())?;
fs::write("server_key.pem", server_key.serialize_pem())?;
本文来自博客园,作者:星墨,转载请注明原文链接:https://www.cnblogs.com/yada/p/20727168

浙公网安备 33010602011771号