从 RSA 私钥和公钥生成 PKCS#10 CSR。怎么办?

问题描述 投票:0回答:1

我是 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 rsaStruct 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);
}
rust openssl rsa
1个回答
0
投票

使用 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。

© www.soinside.com 2019 - 2024. All rights reserved.