From 72f332db4738de1c6b300cb7c5840f94591b343a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=BB=E9=AD=82=E5=9C=A3=E4=BD=BF?= Date: Sat, 18 Jan 2025 23:35:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0Ling=20Transmit=20V1.1?= =?UTF-8?q?=E5=8D=8F=E8=AE=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 + Cargo.toml | 16 ++++ README.md | 3 + src/bin/main.rs | 7 ++ src/close_sender.rs | 51 +++++++++++++ src/lib.rs | 4 + src/packet/code.rs | 26 +++++++ src/packet/mod.rs | 109 +++++++++++++++++++++++++++ src/server/Client.rs | 175 +++++++++++++++++++++++++++++++++++++++++++ src/server/accept.rs | 116 ++++++++++++++++++++++++++++ src/server/mod.rs | 126 +++++++++++++++++++++++++++++++ src/ssl/mod.rs | 102 +++++++++++++++++++++++++ 12 files changed, 738 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 src/bin/main.rs create mode 100644 src/close_sender.rs create mode 100644 src/lib.rs create mode 100644 src/packet/code.rs create mode 100644 src/packet/mod.rs create mode 100644 src/server/Client.rs create mode 100644 src/server/accept.rs create mode 100644 src/server/mod.rs create mode 100644 src/ssl/mod.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..408b8a5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +Cargo.lock +.idea \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..e257768 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "LingTransmit" +version = "0.1.0" +edition = "2021" + +[lib] +name = "LingTransmit" +crate-type = ["staticlib"] + + +[dependencies] +openssl = "0.10.68" +tokio = { version = "1.43.0", features = ["full"] } +async-trait = "0.1.85" +tokio-macros = "2.5.0" +log = "0.4.25" diff --git a/README.md b/README.md new file mode 100644 index 0000000..96fbc4b --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# 零点传输协议 + +用于控制数据包如何交换,工作在TCP协议栈之上。 \ No newline at end of file diff --git a/src/bin/main.rs b/src/bin/main.rs new file mode 100644 index 0000000..2e21c16 --- /dev/null +++ b/src/bin/main.rs @@ -0,0 +1,7 @@ +// 版权所有 (c) ling 保留所有权利。 +// 除非另行说明,否则仅允许在LingTransmit中使用此文件中的代码。 +// +// 由 ling 创建于 2025/1/18. +#![allow(non_snake_case)] + +fn main() {} diff --git a/src/close_sender.rs b/src/close_sender.rs new file mode 100644 index 0000000..2ec9913 --- /dev/null +++ b/src/close_sender.rs @@ -0,0 +1,51 @@ +// 版权所有 (c) ling 保留所有权利。 +// 除非另行说明,否则仅允许在LingTransmit中使用此文件中的代码。 +// +// 由 ling 创建于 2025/1/18. +#![allow(non_snake_case)] + +use tokio::sync::broadcast::error::RecvError; +use tokio::sync::broadcast::Receiver; +use tokio::sync::broadcast::Sender; +use tokio::sync::{broadcast, Mutex, MutexGuard}; + +/// 用于广播关闭消息的通道 +pub struct CloseSender { + sender: Mutex>, + receive: Mutex>, +} + +impl CloseSender { + pub fn new() -> Self { + let (close_tx, close_rx) = broadcast::channel::(1); + CloseSender { + sender: Mutex::new(close_tx), + receive: Mutex::new(close_rx), + } + } + + pub async fn clone(&self) -> Self { + let lock = self.sender.lock().await; + CloseSender { + sender: Mutex::new(lock.clone()), + receive: Mutex::new(lock.subscribe()), + } + } + + /// 广播关闭消息 + pub async fn send_close(&self) { + let lock = self.sender.lock().await; + let _ = lock.send(0); + } + + pub async fn send_close_value(&self, value: i8) { + let lock = self.sender.lock().await; + let _ = lock.send(value); + } + + /// 等待收到关闭消息 + pub async fn wait_close(&self) -> i8 { + let value = self.receive.lock().await.recv().await; + value.unwrap_or_else(|_| -1) + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..c80015b --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,4 @@ +pub mod server; +pub mod close_sender; +pub mod packet; +pub mod ssl; \ No newline at end of file diff --git a/src/packet/code.rs b/src/packet/code.rs new file mode 100644 index 0000000..cdcb518 --- /dev/null +++ b/src/packet/code.rs @@ -0,0 +1,26 @@ +// 版权所有 (c) ling 保留所有权利。 +// 除非另行说明,否则仅允许在LingTransmit中使用此文件中的代码。 +// +// 由 ling 创建于 2025/1/18. +#![allow(non_snake_case)] + +/// SYN V1 +pub const LING_SYN_V1: i32 = 0x20040202; +/// 数据包开始魔数 +pub const LING_START: i32 = 0x20040202; +/// 数据包尾部魔数 +pub const LING_STOP: i32 = 0x20030507; +/// Ling - 1.0 数据包最大长度 +pub const MAX_SIZE_V1_0: i32 = 32 * 1024; +/// Ling - 1.1 数据包最大长度 +pub const MAX_SIZE_V1_1: i32 = 512 * 1024; + +/// 服务器确认 +pub const SERVER_ACK: i32 = 99999999; +/// 服务器错误 +pub const SERVER_ERROR: i32 = 100000000; + +/// 用户接口 +pub const API_TYPE_ASK: i32 = 1; +/// 交换密钥 +pub const API_TYPE_PUSH_AES_KEY: i32 = 4; \ No newline at end of file diff --git a/src/packet/mod.rs b/src/packet/mod.rs new file mode 100644 index 0000000..f17df74 --- /dev/null +++ b/src/packet/mod.rs @@ -0,0 +1,109 @@ +// 版权所有 (c) ling 保留所有权利。 +// 除非另行说明,否则仅允许在LingTransmit中使用此文件中的代码。 +// +// 由 ling 创建于 2025/1/18. +#![allow(non_snake_case)] + +pub mod code; + +use crate::packet::code::*; +use crate::server::accept::OwnedReadHalfAbstraction; +use crate::server::Client::Client; +use std::fmt::format; +use std::sync::atomic::Ordering; +use std::{error, io}; +use tokio::io::AsyncReadExt; + +/// 数据包 +pub enum NetworkPackets { + /// 客户端请求执行SYN V1握手,发送服务器公钥证书 + SynV1, + /// 用户接口 + UserAsk(Vec), + /// 设定会话密钥 + PushAesKey(Vec), +} + +/// 从字节流中读取一个数据包 +pub async fn read_packet( + read: &mut Box, + client: &Client, +) -> io::Result { + //根据协议,通信伊始收到 SYN V1 信息,则使用V1协议加密通信 + //在此实现中,彻底摈弃了未加密的不安全数据。 + //如果客户端没有建立SSL安全连接就开始通信,则直接掐断。 + if client.syn_version.load(Ordering::Acquire) == 0 + && !client.is_key_negotiation.load(Ordering::Acquire) + { + let syn = read.read_i32().await?; + if syn != LING_SYN_V1 { + return Err(make_error("客户端尝试使用未加密连接交换数据")); + } + client.is_key_negotiation.store(true, Ordering::Release); + //客户端请求V1握手 + return Ok(NetworkPackets::SynV1); + } + //读取数据包长度 + let mut size = read.read_i32().await?; + // 在旧版本的协议中,没有魔数标记数据包开始,数据包通过 int32_t 类型的size作为开始。 + // 如果传输过程中出错,导致读取位置发生些许偏差,则size不准,可能错误分配堆内存,带来安全隐患。 + // 自 Ling V1.1开始,数据包头部必须使用 LING_START 开始 + // 但为了兼容旧的应用,允许 32kb 以下的数据包不附带魔数。 + if size > MAX_SIZE_V1_0 { + if size != LING_START { + return Err(make_error( + "客户端发送的数据包过大(Ling Transmit V1.0限制32KB)!", + )); + } + //由于size实际上读取的是 LING_START 魔数,所以要重新读取四个字节作为数据包实际大小 + size = read.read_i32().await?; + //附带魔数后,将数据包长度限制提高到 512kb + if size > MAX_SIZE_V1_1 { + return Err(make_error( + "客户端发送的数据包过大(Ling Transmit V1.1限制512KB)!", + )); + } + } + //根据协议,包体大小必须是正整数,不能为0 + if size <= 0 { + return Err(make_error(format!( + "客户端发送了错误的数据包大小:{}", + size + ))); + } + + // 数据包类型 + let data_type = match read.read_i32().await? { + API_TYPE_ASK => API_TYPE_ASK, + API_TYPE_PUSH_AES_KEY => API_TYPE_PUSH_AES_KEY, + num => { + return Err(make_error(format!("未知的数据包类型:{}", num))); + } + }; + // 读取包体 + let mut buffer = Vec::new(); + buffer.resize(size as usize, 0); + let read_size = read.read_exact(&mut buffer).await?; + if read_size != size as usize { + return Err(make_error(format!( + "残缺数据包:读取到{}字节,共{}字节", + read_size, size + ))); + } + + match data_type { + API_TYPE_ASK => Ok(NetworkPackets::UserAsk(buffer)), + API_TYPE_PUSH_AES_KEY => Ok(NetworkPackets::PushAesKey(buffer)), + _ => Err(make_error("未知的数据包类型")), + } +} + +fn make_error(str: E) -> io::Error +where + E: Into> + std::fmt::Display, +{ + io::Error::new( + io::ErrorKind::NetworkUnreachable, + format!("协议错误:{}", str), + ) +} diff --git a/src/server/Client.rs b/src/server/Client.rs new file mode 100644 index 0000000..b4e6ce8 --- /dev/null +++ b/src/server/Client.rs @@ -0,0 +1,175 @@ +// 版权所有 (c) ling 保留所有权利。 +// 除非另行说明,否则仅允许在LingTransmit中使用此文件中的代码。 +// +// 由 ling 创建于 2025/1/18. +#![allow(non_snake_case)] + +use crate::close_sender::CloseSender; +use crate::packet::code::{SERVER_ACK, SERVER_ERROR}; +use crate::packet::{read_packet, NetworkPackets}; +use crate::server::accept::{OwnedReadHalfAbstraction, OwnedWriteHalfAbstraction, SocketAddr}; +use crate::server::ClientID; +use crate::ssl::ServerCert; +use log::{error, info}; +use openssl::rsa::Padding; +use std::io; +use std::string::FromUtf8Error; +use std::sync::atomic::{AtomicBool, AtomicI32}; +use std::sync::{Arc, OnceLock}; +use std::time::Duration; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio::sync::Mutex; + +pub type ReadSoc = Mutex>>; +pub type WriteSoc = Mutex>; + +/// 服务器侧的Client抽象 +pub struct Client { + /// 服务器关闭 + server_close: CloseSender, + /// 连接关闭 + client_close: CloseSender, + read_soc: ReadSoc, + write_soc: WriteSoc, + pub id: ClientID, + pub addr: SocketAddr, + /// 协议版本 + pub syn_version: AtomicI32, + /// 是否正在进行密钥协商 + pub is_key_negotiation: AtomicBool, + /// 会话密钥 + pub key: OnceLock, + /// 服务器证书 + cert: Arc, +} + +impl Client { + pub fn new( + server_close: CloseSender, + client_close: CloseSender, + read_soc: Box, + write_soc: Box, + id: ClientID, + addr: SocketAddr, + cert: Arc, + ) -> Self { + Client { + server_close, + client_close, + read_soc: Mutex::new(Some(read_soc)), + write_soc: Mutex::new(write_soc), + id, + addr, + syn_version: AtomicI32::new(0), + is_key_negotiation: AtomicBool::new(false), + key: OnceLock::new(), + cert, + } + } + + /// 挂断连接 + pub(super) async fn close(&self) { + let mut lock = self.read_soc.lock().await; + *lock = None; + drop(lock); + let mut lock = self.write_soc.lock().await; + if let Err(err) = lock.shutdown().await { + error!("关闭 {} 号客户端的写入端失败:{}", self.id, err.to_string()); + } + } + + /// 开始处理该客户端的请求 + pub async fn start(&self) { + loop { + //从字节流中读取一个数据包 + let packet = tokio::select! { + packet = async { + let mut lock = self.read_soc.lock().await; + match *lock { + None => { + Err(io::Error::new(io::ErrorKind::NotFound,"读取端已经被挂断")) + } + Some(ref mut val) => { + read_packet(val,self).await + } + } + } => { + match packet { + Ok(val) => {val} + Err(err) => { + info!("{} 号连接读取数据包出错:{}",self.id,err.to_string()); + return; + } + } + } + _ = self.server_close.wait_close() => { + info!("{} 号连接被挂断",self.id); + return; + } + _ = self.client_close.wait_close() => { + info!("{} 号连接被挂断",self.id); + return; + } + }; + + //处理客户端请求 + //将数据包的读取和处理放在不同的select!中,确保数据包的处理过程不会被关闭信号打断 + tokio::select! { + result = self.process_packet(packet) => { + if let Err(err) = result { + error!("{} 号连接请求处理出错:{}", self.id, err.to_string()); + return; + } + } + _ = tokio::time::sleep(Duration::from_secs(15)) => { + error!("{} 号连接的请求处理超时!",self.id); + return; + } + } + } + } + + /// 处理客户端请求 + async fn process_packet(&self, packet: NetworkPackets) -> io::Result<()> { + match packet { + NetworkPackets::SynV1 => self.syn_v1().await, + NetworkPackets::UserAsk(_) => Ok(()), + NetworkPackets::PushAesKey(data) => self.client_push_key(&data).await, + } + } + + /// 客户端推送会话密钥 + async fn client_push_key(&self, buff: &Vec) -> io::Result<()> { + let rsa = self.cert.private_key.rsa()?; + + let mut data = Vec::new(); + data.resize(rsa.size() as usize, 0u8); + + //解密会话密钥 + rsa.private_decrypt(buff, &mut data, Padding::PKCS1)?; + + let key = match String::from_utf8(data) { + Ok(key) => key, + Err(_) => { + return Err(io::Error::new(io::ErrorKind::NotFound, "解密会话密钥失败")); + } + }; + let mut send = self.write_soc.lock().await; + if let Err(_) = self.key.set(key.clone()) { + //重复推送,拒绝密钥 + send.write_i32(SERVER_ERROR).await?; + return Ok(()); + } + send.write_i32(SERVER_ACK).await?; + Ok(()) + } + + /// 发送服务器证书 + async fn syn_v1(&self) -> io::Result<()> { + let certificate = self.cert.certificate.to_pem()?; + let mut send = self.write_soc.lock().await; + send.write_i64(certificate.len() as i64).await?; + send.write(&certificate).await?; + Ok(()) + } +} diff --git a/src/server/accept.rs b/src/server/accept.rs new file mode 100644 index 0000000..eb1dce8 --- /dev/null +++ b/src/server/accept.rs @@ -0,0 +1,116 @@ +// 版权所有 (c) ling 保留所有权利。 +// 除非另行说明,否则仅允许在LingTransmit中使用此文件中的代码。 +// +// 由 ling 创建于 2025/1/18. +#![allow(non_snake_case)] + +use async_trait::async_trait; +use tokio::io; +use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; +use tokio::net::{tcp, unix, TcpListener, UnixListener}; + +/// 读取抽象,使用小端序 +#[async_trait] +pub trait OwnedReadHalfAbstraction: AsyncRead + Unpin + Send + Sync { + async fn read_i32(&mut self) -> io::Result { + let mut buffer = [0u8; 4]; + self.read_exact(&mut buffer).await?; + Ok(i32::from_le_bytes(buffer)) + } + + async fn read_i64(&mut self) -> io::Result { + let mut buffer = [0u8; 8]; + self.read_exact(&mut buffer).await?; + Ok(i64::from_le_bytes(buffer)) + } + + async fn read_u32(&mut self) -> io::Result { + let mut buffer = [0u8; 4]; + self.read_exact(&mut buffer).await?; + Ok(u32::from_le_bytes(buffer)) + } + + async fn read_u64(&mut self) -> io::Result { + let mut buffer = [0u8; 8]; + self.read_exact(&mut buffer).await?; + Ok(u64::from_le_bytes(buffer)) + } +} + +/// 写入抽象,使用小端序 +#[async_trait] +pub trait OwnedWriteHalfAbstraction: AsyncWrite + Unpin + Send + Sync { + async fn write_i32(&mut self, value: i32) -> io::Result { + self.write(&value.to_le_bytes()).await + } + + async fn write_i64(&mut self, value: i64) -> io::Result { + self.write(&value.to_le_bytes()).await + } + + async fn write_u32(&mut self, value: u32) -> io::Result { + self.write(&value.to_le_bytes()).await + } + + async fn write_u64(&mut self, value: u64) -> io::Result { + self.write(&value.to_le_bytes()).await + } +} + +#[async_trait] +impl OwnedReadHalfAbstraction for tcp::OwnedReadHalf {} + +#[async_trait] +impl OwnedReadHalfAbstraction for unix::OwnedReadHalf {} + +#[async_trait] +impl OwnedWriteHalfAbstraction for tcp::OwnedWriteHalf {} + +#[async_trait] +impl OwnedWriteHalfAbstraction for unix::OwnedWriteHalf {} + +#[async_trait] +pub trait AcceptSocket { + async fn accept( + &self, + ) -> io::Result<( + Box, + Box, + SocketAddr, + )>; +} + +pub enum SocketAddr { + TCP(std::net::SocketAddr), + Unix(unix::SocketAddr), +} + +#[async_trait] +impl AcceptSocket for TcpListener { + async fn accept( + &self, + ) -> io::Result<( + Box, + Box, + SocketAddr, + )> { + let (socket, addr) = self.accept().await?; + let (read, write) = socket.into_split(); + Ok((Box::new(read), Box::new(write), SocketAddr::TCP(addr))) + } +} + +#[async_trait] +impl AcceptSocket for UnixListener { + async fn accept( + &self, + ) -> io::Result<( + Box, + Box, + SocketAddr, + )> { + let (socket, addr) = self.accept().await?; + let (read, write) = socket.into_split(); + Ok((Box::new(read), Box::new(write), SocketAddr::Unix(addr))) + } +} diff --git a/src/server/mod.rs b/src/server/mod.rs new file mode 100644 index 0000000..0155840 --- /dev/null +++ b/src/server/mod.rs @@ -0,0 +1,126 @@ +// 版权所有 (c) ling 保留所有权利。 +// 除非另行说明,否则仅允许在LingTransmit中使用此文件中的代码。 +// +// 由 ling 创建于 2025/1/18. +#![allow(non_snake_case)] + +pub mod Client; +pub mod accept; + +use crate::close_sender::CloseSender; +use crate::server::accept::AcceptSocket; +use crate::ssl::ServerCert; +use async_trait::async_trait; +use log::{debug, error}; +use std::collections::HashMap; +use std::path::Path; +use std::sync::atomic::{AtomicU64, Ordering}; +use std::sync::{mpsc, Arc}; +use tokio::io; +use tokio::io::{AsyncRead, AsyncWrite}; +use tokio::net::UnixListener; +use tokio::net::{TcpListener, ToSocketAddrs}; +use tokio::sync::{broadcast, Mutex}; + +pub type ClientID = u64; +pub type ClientList = Arc>>>; + +/// 服务器抽象 +pub struct Server { + listener: Box, + close_sender: CloseSender, + client_list: ClientList, + next_id: AtomicU64, + cert: Arc, +} + +impl Server { + fn new(listener: Box, cert: ServerCert) -> Self { + Server { + listener, + close_sender: CloseSender::new(), + client_list: Arc::new(Mutex::new(HashMap::new())), + next_id: AtomicU64::new(0), + cert: Arc::new(cert), + } + } + + pub async fn new_tcp(addr: A, cert: ServerCert) -> io::Result { + let listener = TcpListener::bind(addr).await?; + Ok(Server::new(Box::new(listener), cert)) + } + + pub async fn new_unix

(path: P, cert: ServerCert) -> io::Result + where + P: AsRef, + { + let unix = UnixListener::bind(path)?; + Ok(Server::new(Box::new(unix), cert)) + } + + /// 广播关闭消息 + pub async fn close(&self) { + self.close_sender.send_close().await; + } + + /// 获取在线客户端列表 + pub fn get_client_list(&self) -> ClientList { + self.client_list.clone() + } + + /// 挂断一个客户端 + pub async fn close_client(&self, id: ClientID) { + Self::close_client_form_arc(&self.client_list, id).await; + } + + pub async fn close_client_form_arc(list: &ClientList, id: ClientID) { + let mut lock = list.lock().await; + if let Some(client) = lock.get(&id) { + client.close().await; + lock.remove(&id); + } + } + + /// 开始接收客户端连接 + pub async fn start_accept(&self) { + tokio::select! { + _ = async { + loop { + if let Err(err) = self.accept_client().await { + error!("接受连接失败:{}",err.to_string()); + } + } + } => {} + _ = self.close_sender.wait_close() => { + debug!("停止接受客户端连接"); + } + } + } + + async fn accept_client(&self) -> io::Result<()> { + let (read, write, addr) = self.listener.accept().await?; + let id = self.next_id.fetch_add(1, Ordering::SeqCst); + let close = CloseSender::new(); + let client = Arc::new(Client::Client::new( + self.close_sender.clone().await, + close, + read, + write, + id, + addr, + self.cert.clone(), + )); + + let mut lock = self.client_list.lock().await; + lock.insert(id, client.clone()); + drop(lock); + + let list = self.get_client_list(); + tokio::spawn(async move { + client.start().await; + //当连接的事件轮退出,则自动挂断 + Self::close_client_form_arc(&list, id).await; + }); + Ok(()) + } +} diff --git a/src/ssl/mod.rs b/src/ssl/mod.rs new file mode 100644 index 0000000..9393a9e --- /dev/null +++ b/src/ssl/mod.rs @@ -0,0 +1,102 @@ +// 版权所有 (c) ling 保留所有权利。 +// 除非另行说明,否则仅允许在LingTransmit中使用此文件中的代码。 +// +// 由 ling 创建于 2025/1/18. +#![allow(non_snake_case)] + +use openssl::hash::MessageDigest; +use openssl::pkey::{PKey, Private, Public}; +use openssl::rsa::Rsa; +use openssl::sign::{Signer, Verifier}; +use openssl::x509::X509; +use std::path::{Path, PathBuf}; +use std::{fs, io}; + +/// 服务器证书 +pub struct ServerCert { + /// 私钥 + pub private_key: PKey, + /// 公钥 + pub public_key: PKey, + /// 证书文件 + pub certificate: X509, +} + +impl ServerCert { + pub fn init(certificate_path: &PathBuf, private_path: &PathBuf) -> io::Result { + let cert = Self::load_public(&certificate_path)?; + let private_key = Self::load_private(private_path)?; + Ok(Self::init_key(cert, private_key)?) + } + + pub fn init_password( + certificate_path: &PathBuf, + private_path: &PathBuf, + password: &str, + ) -> io::Result { + let cert = Self::load_public(&certificate_path)?; + let private_key = Self::load_private_password(private_path, password)?; + Ok(Self::init_key(cert, private_key)?) + } + + pub fn init_buffer(cert: &Vec, private: &Vec) -> io::Result { + let x509 = X509::from_pem(cert)?; + let private_key = PKey::private_key_from_pem(private)?; + Self::init_key(x509, private_key) + } + + pub fn init_buffer_password( + cert: &Vec, + private: &Vec, + password: &str, + ) -> io::Result { + let x509 = X509::from_pem(cert)?; + let private_key = PKey::private_key_from_pem_passphrase(private, password.as_bytes())?; + Self::init_key(x509, private_key) + } + + fn init_key(certificate: X509, private_key: PKey) -> io::Result { + //检查证书和私钥是否匹配 + let message = b"test message"; + //先使用私钥签名数据 + let mut signer = Signer::new(MessageDigest::sha256(), &private_key)?; + signer.update(message)?; + let signature = signer.sign_to_vec()?; + + //然后使用公钥验证签名 + let public_key = certificate.public_key()?; + let mut verifier = Verifier::new(MessageDigest::sha256(), &public_key)?; + verifier.update(message)?; + if !verifier.verify(&signature)? { + return Err(io::Error::new( + io::ErrorKind::NotFound, + "提供的证书和私钥不匹配!", + )); + } + drop(verifier); + + Ok(ServerCert { + private_key, + public_key, + certificate, + }) + } + + fn load_public(certificate_path: &PathBuf) -> io::Result { + let cert_data = fs::read(certificate_path)?; + Ok(X509::from_pem(&cert_data)?) + } + + fn load_private(private_path: &PathBuf) -> io::Result> { + let key_data = fs::read(private_path)?; + Ok(PKey::private_key_from_pem(&key_data)?) + } + + fn load_private_password(private_path: &PathBuf, password: &str) -> io::Result> { + let key_data = fs::read(private_path)?; + Ok(PKey::private_key_from_pem_passphrase( + &key_data, + password.as_bytes(), + )?) + } +}