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())?;
posted @ 2026-06-23 11:59  星墨  阅读(3)  评论(0)    收藏  举报