feat(project):放置全新的项目结构。
This commit is contained in:
11
cert_lib/Cargo.toml
Normal file
11
cert_lib/Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "cert_lib"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.81"
|
||||
openssl = "0.10.64"
|
||||
thiserror = "1.0.58"
|
9
cert_lib/src/errors.rs
Normal file
9
cert_lib/src/errors.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum CertificateGenerateError {
|
||||
#[error("Error generating RSA key")]
|
||||
X509Error(#[from] openssl::error::ErrorStack),
|
||||
#[error("IO Error")]
|
||||
IOError(#[from] std::io::Error),
|
||||
}
|
101
cert_lib/src/lib.rs
Normal file
101
cert_lib/src/lib.rs
Normal file
@@ -0,0 +1,101 @@
|
||||
use std::fs::{self, File};
|
||||
use std::io::{BufWriter, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::{io, path::Path};
|
||||
|
||||
use openssl::bn::BigNumContext;
|
||||
use openssl::x509::X509;
|
||||
use openssl::{
|
||||
asn1::{Asn1Integer, Asn1Time},
|
||||
bn::BigNum,
|
||||
pkey::PKey,
|
||||
rsa::Rsa,
|
||||
x509::X509Builder,
|
||||
};
|
||||
|
||||
pub mod errors;
|
||||
mod root_certificate;
|
||||
|
||||
/// 生成证书,公钥保存为.pem文件,私钥保存为.key文件
|
||||
///
|
||||
/// - `storage_path`:证书存储路径
|
||||
/// - `certificate_name`:证书名称
|
||||
/// - `key_length`:密钥长度
|
||||
/// - `available_days`:证书有效天数
|
||||
/// - `version`:证书版本
|
||||
/// - `serial_number`:证书序列号,如果不设定则默认为1
|
||||
pub fn generate_certificate(
|
||||
storage_path: &str,
|
||||
certificate_name: &str,
|
||||
key_length: u32,
|
||||
available_days: u32,
|
||||
version: i32,
|
||||
serial_number: Option<u32>,
|
||||
) -> anyhow::Result<()> {
|
||||
let rsa = Rsa::generate(key_length)?;
|
||||
let private_key = rsa.private_key_to_pem()?;
|
||||
let mut builder = X509Builder::new()?;
|
||||
builder.set_version(version)?;
|
||||
let pkey = PKey::from_rsa(rsa)?;
|
||||
builder.set_pubkey(&pkey)?;
|
||||
|
||||
let not_before = Asn1Time::days_from_now(0)?;
|
||||
let not_after = Asn1Time::days_from_now(available_days)?;
|
||||
builder.set_not_before(¬_before)?;
|
||||
builder.set_not_after(¬_after)?;
|
||||
let serial_number = BigNum::from_u32(serial_number.unwrap_or(1))?;
|
||||
let sn = Asn1Integer::from_bn(&serial_number)?;
|
||||
builder.set_serial_number(&sn)?;
|
||||
|
||||
let certificate = builder.build();
|
||||
|
||||
let store_path = PathBuf::from(storage_path);
|
||||
ensure_path_exists(&store_path).unwrap();
|
||||
|
||||
let cert_path = store_path.clone().join(format!("{}.pem", certificate_name));
|
||||
let cert_file = File::create(cert_path)?;
|
||||
let mut writer = BufWriter::new(cert_file);
|
||||
writer.write_all(&certificate.to_pem()?)?;
|
||||
writer.flush()?;
|
||||
|
||||
let private_key_path = store_path.join(format!("{}.key", certificate_name));
|
||||
let private_key_file = File::create(private_key_path)?;
|
||||
let mut writer = BufWriter::new(private_key_file);
|
||||
writer.write_all(&private_key)?;
|
||||
writer.flush()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 确保指定路径存在,如果不存在则创建
|
||||
///
|
||||
/// - `target_path`:目标路径
|
||||
fn ensure_path_exists<P: AsRef<Path>>(target_path: P) -> Result<(), io::Error> {
|
||||
let path = target_path.as_ref();
|
||||
if !path.exists() {
|
||||
fs::create_dir_all(path)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 计算用于net-filter中power插件中Equal所使用的值。
|
||||
pub fn calculate_power_euqal_result(cert: X509) -> anyhow::Result<String> {
|
||||
let x = BigNum::from_slice(cert.signature().as_slice())?;
|
||||
let y = BigNum::from_u32(65537)?;
|
||||
let root_cert_pub_key = root_certificate::x509_certificate()?.public_key()?.rsa()?;
|
||||
let z = root_cert_pub_key.n();
|
||||
let cert_pub_key = cert.public_key()?.rsa()?;
|
||||
let n = cert_pub_key.n();
|
||||
|
||||
let mut ctx = BigNumContext::new()?;
|
||||
let mut result = BigNum::new()?;
|
||||
result.mod_exp(&x, &y, &n, &mut ctx)?;
|
||||
Ok(format!(
|
||||
"EQUAL,{},{},{}->{}",
|
||||
x.to_dec_str()?,
|
||||
y.to_dec_str()?,
|
||||
z.to_dec_str()?,
|
||||
result.to_dec_str()?
|
||||
))
|
||||
}
|
42
cert_lib/src/root_certificate.rs
Normal file
42
cert_lib/src/root_certificate.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
use openssl::{error::ErrorStack, x509::X509};
|
||||
|
||||
/// 根证书内容。
|
||||
fn certificate() -> String {
|
||||
String::from(
|
||||
r#"-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----"#,
|
||||
)
|
||||
}
|
||||
|
||||
/// 获取x509格式根证书。
|
||||
pub fn x509_certificate() -> Result<X509, ErrorStack> {
|
||||
X509::from_pem(certificate().as_bytes())
|
||||
}
|
Reference in New Issue
Block a user