我是 Rust 新手,终于找到了一些可以学习的东西,让我在整个陡峭的学习曲线中保持兴趣;加密。
我想知道 Rust 是否足够成熟,可以产生与以下
openssl
命令相同的输出 但不使用 openssl
。
sudo openssl req \
-new \
-newkey rsa:2048 \
-nodes \
-keyout $HOME/www_example_com.key \
-out $HOME/www_example_com.csr \
-config /etc/ssl/openssl.cnf \
-subj "/C=US/ST=Utah/L=Salt Lake City/O=Xmpl, Inc./OU=IT Department/CN=www.example.com/[email protected]"
到目前为止,我已经找到了创建 Crate rsa 和 Struct std::path::Path,它允许我创建 (n) 位的 RSA 公钥和私钥并将它们导出为 PEM 文件。
然后我找到了 Crate rcgen,其中似乎包含 Struct rcgen::CertificateSigningRequest,这就是我迷路的地方。
如何产生与 openssl 命令相同的输出?
到目前为止的 Rust 代码:
use rsa::{RsaPrivateKey, RsaPublicKey, pkcs1::{EncodeRsaPrivateKey, EncodeRsaPublicKey, LineEnding}};
use std::path::Path;
use rcgen::CertificateSigningRequest;
fn main() {
let mut rng = rand::thread_rng();
let bits = 2048;
let priv_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
let pub_key = RsaPublicKey::from(&priv_key);
// Encode private key to PEM
// let priv_pem = priv_key.to_pkcs1_pem(LineEnding::LF).expect("failed to encode private key");
// println!("Private Key PEM:\n{:#?}", priv_pem);
// Optionally, write to a file
priv_key.write_pkcs1_pem_file(Path::new("www_example_com_prv.key"), LineEnding::LF).expect("failed to write private key");
// Encode public key to PEM
// let pub_pem = pub_key.to_pkcs1_pem(LineEnding::LF).expect("failed to encode public key");
// println!("Public Key PEM:\n{:#?}", pub_pem);
// Optionally, write to a file
pub_key.write_pkcs1_pem_file(Path::new("www_example_com_pub.key"), LineEnding::LF).expect("failed to write public key");
println!("RSA {}bit Private Key generated.", bits);
println!("RSA {}bit Public Key generated.", bits);
}
使用 rcgen 创建 CSR 实际上很简单:您使用
CertificateParams
指定证书参数和密钥,使用 Certificate
创建
Certificate::from_params()
实例,并可以使用它来使用 创建 CSR Certificate#serialize_request_pem()
:
示例:
use rcgen::{Certificate, CertificateParams, DnType, DistinguishedName, PKCS_RSA_SHA256, KeyPair};
fn main() {
let pkcs8 = "-----BEGIN PRIVATE KEY-----
MIIEv...fke4LZo5mOS10
-----END PRIVATE KEY-----";
let keypair = KeyPair::from_pem(pkcs8).unwrap();
let mut distinguished_name = DistinguishedName::new();
distinguished_name.push(DnType::CountryName, "US");
distinguished_name.push(DnType::StateOrProvinceName, "Utah");
distinguished_name.push(DnType::LocalityName, "Salt Lake City");
distinguished_name.push(DnType::OrganizationName, "Xmpl, Inc.");
distinguished_name.push(DnType::OrganizationalUnitName, "IT Department");
distinguished_name.push(DnType::CommonName, "www.example.com");
distinguished_name.push(DnType::CustomDnType(vec![1, 2, 840, 113549, 1, 9, 1]), "[email protected]");
let mut params: CertificateParams = Default::default();
params.alg = &PKCS_RSA_SHA256;
params.distinguished_name = distinguished_name;
params.key_pair = Some(keypair);
let cert: Certificate = Certificate::from_params(params).unwrap();
println!("{}", cert.serialize_request_pem().unwrap());
}
请注意,上面示例代码中的私钥必须是 PKCS#8 格式,而您的代码使用 PKCS#1。切换到 PKCS#8 很简单:
use rsa::{RsaPrivateKey, RsaPublicKey, pkcs8::{EncodePrivateKey, EncodePublicKey, LineEnding}};
fn main() {
let mut rng = rand::thread_rng();
let bits = 2048;
let priv_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
let pub_key = RsaPublicKey::from(&priv_key);
// Encode private key in PKCS#8 format to PEM // added for private key in PKCS#8 format
let priv_pkcs8_pem = priv_key.to_pkcs8_pem(LineEnding::LF).expect("failed to encode private key");
println!("Private Key PEM (PKCS#8):\n{:#?}", priv_pkcs8_pem);
// Encode public key in X.509/SPKI format to PEM // added for public key in X.509/SPKI format
let pub_spki_pem = pub_key.to_public_key_pem(LineEnding::LF).expect("failed to encode public key");
println!("Public Key PEM (X.509/SPKI):\n{:#?}", pub_spki_pem);
}
以这种方式创建的 CSR 对应于使用 OpenSSL (v3.0.0) 创建的 CSR。