From 9a913b4bf45d160442eb8a5a916cdb18ffaee92d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=B6=9B?= Date: Mon, 3 Jul 2023 15:45:14 +0800 Subject: [PATCH] =?UTF-8?q?feat(rsa):=E5=9F=BA=E6=9C=AC=E5=AE=8C=E6=88=90R?= =?UTF-8?q?SA=E7=B3=BB=E5=88=97=E5=8A=A0=E5=AF=86=E7=AE=97=E6=B3=95?= =?UTF-8?q?=E5=92=8C=E7=AD=BE=E5=90=8D=E7=AE=97=E6=B3=95=E7=9A=84=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 2 + README.md | 10 +- src/encryption/mod.rs | 1 + src/encryption/rsa.rs | 338 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 346 insertions(+), 5 deletions(-) create mode 100644 src/encryption/rsa.rs diff --git a/Cargo.toml b/Cargo.toml index 5b14e99..397f661 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,8 @@ hmac-sha512 = "1.1.5" image = "0.24.6" md-5 = "0.10.5" rand = "0.8.5" +rsa = { version = "0.9.2", features = ["sha2"] } sha1 = "0.10.5" +sha2 = "0.10.7" thiserror = "1.0.40" uuid = { version = "1.4.0", features = ["v4", "fast-rng"] } diff --git a/README.md b/README.md index a7968f1..3629485 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,10 @@ Rust 中可以使用的常用辅助功能工具箱。主要配备以下功能: - [x] No Padding - [x] ZerosPadding - [x] Pkcs7Padding - - [ ] RSA 加解密算法 - - [ ] 1024 位长 - - [ ] 2048 位长 - - [ ] KeyPair 生成器 + - [x] RSA 加解密算法 + - [x] 1024 位长 + - [x] 2048 位长 + - [x] KeyPair 生成器 - 散列算法。 - [x] Sha512 散列算法 - [x] Sha1 散列算法 @@ -30,7 +30,7 @@ Rust 中可以使用的常用辅助功能工具箱。主要配备以下功能: - [x] UUID 生成器 - [x] short UUID 生成器 - 签名算法 - - [ ] RSA 签名算法 + - [x] RSA 签名算法 - 验证码生成器 - [x] 随机验证码生成算法 - 序列化算法 diff --git a/src/encryption/mod.rs b/src/encryption/mod.rs index be43d67..9c0a042 100644 --- a/src/encryption/mod.rs +++ b/src/encryption/mod.rs @@ -2,6 +2,7 @@ use thiserror::Error; pub mod aes; pub mod des; +pub mod rsa; pub mod tdes; pub enum Padding { diff --git a/src/encryption/rsa.rs b/src/encryption/rsa.rs new file mode 100644 index 0000000..bf0bf0f --- /dev/null +++ b/src/encryption/rsa.rs @@ -0,0 +1,338 @@ +use rsa::{ + pkcs1::{DecodeRsaPrivateKey, DecodeRsaPublicKey, EncodeRsaPrivateKey, EncodeRsaPublicKey}, + pkcs8::{DecodePrivateKey, DecodePublicKey}, + signature::{Keypair, RandomizedSigner, SignatureEncoding, Verifier}, + Pkcs1v15Encrypt, +}; +use sha2::Sha256; +use thiserror::Error; + +pub enum RsaBitSize { + Bit1024, + Bit2048, +} + +#[derive(Debug, Error)] +pub enum RsaCryptionError { + #[error("Invalid public key")] + InvalidPublicKey, + #[error("Invalid private key")] + InvalidPrivateKey, + #[error("Unrecognized private key encoding or encrypted private key")] + UnrecognizedPrivateKeyEncoding, + #[error("Unrecognized public key encoding")] + UnrecognizedPublicKeyEncoding, + #[error("Private key required")] + PrivateKeyRequired, + #[error("Public key required")] + PublicKeyRequired, + #[error("Signing key required")] + SigningKeyRequired, + #[error("Verifying key required")] + VerifyingKeyRequired, + #[error("Failed to process data: {0}")] + CryptionFailed(#[from] rsa::errors::Error), + #[error("Unable to load signature")] + UnableToLoadSignature, + #[error("Signature verification failed")] + VerificationFailed, + #[error("Unable to export private key")] + UnableToExportPrivateKey, + #[error("Unable to export public key")] + UnableToExportPublicKey, +} + +#[derive(Debug)] +pub struct RsaCryptor { + private_key: Option, + public_key: Option, + signing_key: Option>, + verifying_key: Option>, +} + +fn load_binary_private_key(key: &[u8]) -> Result { + let private_key = rsa::RsaPrivateKey::from_pkcs1_der(&key); + if let Ok(private_key) = private_key { + if private_key.validate().is_err() { + return Err(RsaCryptionError::InvalidPrivateKey); + } + return Ok(private_key); + } + let private_key = rsa::RsaPrivateKey::from_pkcs8_der(&key); + if let Ok(private_key) = private_key { + if private_key.validate().is_err() { + return Err(RsaCryptionError::InvalidPrivateKey); + } + return Ok(private_key); + } + Err(RsaCryptionError::UnrecognizedPrivateKeyEncoding) +} + +fn load_text_private_key(pem: &str) -> Result { + let private_key = rsa::RsaPrivateKey::from_pkcs1_pem(pem); + if let Ok(private_key) = private_key { + if private_key.validate().is_err() { + return Err(RsaCryptionError::InvalidPrivateKey); + } + return Ok(private_key); + } + let private_key = rsa::RsaPrivateKey::from_pkcs8_pem(pem); + if let Ok(private_key) = private_key { + if private_key.validate().is_err() { + return Err(RsaCryptionError::InvalidPrivateKey); + } + return Ok(private_key); + } + Err(RsaCryptionError::UnrecognizedPrivateKeyEncoding) +} + +fn load_binary_public_key(key: &[u8]) -> Result { + let public_key = rsa::RsaPublicKey::from_pkcs1_der(&key); + if let Ok(public_key) = public_key { + return Ok(public_key); + } + let public_key = rsa::RsaPublicKey::from_public_key_der(&key); + if let Ok(public_key) = public_key { + return Ok(public_key); + } + Err(RsaCryptionError::UnrecognizedPublicKeyEncoding) +} + +fn load_text_public_key(pem: &str) -> Result { + let public_key = rsa::RsaPublicKey::from_pkcs1_pem(pem); + if let Ok(public_key) = public_key { + return Ok(public_key); + } + let public_key = rsa::RsaPublicKey::from_public_key_pem(pem); + if let Ok(public_key) = public_key { + return Ok(public_key); + } + Err(RsaCryptionError::UnrecognizedPublicKeyEncoding) +} + +impl RsaCryptor { + /// 创建一个完全空白的 RSA 加密器。其中私钥、公钥、签名私钥和签名公钥都是空的,需要通过其他方法加载后方可使用。 + pub fn new_empty() -> Self { + Self { + private_key: None, + public_key: None, + signing_key: None, + verifying_key: None, + } + } + + /// 创建一个指定位数的 RSA 加密器,同时生成一套随机密钥。 + /// 如果不能正常生成私钥,则直接返回错误。 + /// + /// - `bit_size`:密钥位数,目前支持 1024 位和 2048 位。 + pub fn new(bit_size: RsaBitSize) -> Result { + let mut rng = rand::thread_rng(); + let bit_size = match bit_size { + RsaBitSize::Bit1024 => 1024, + RsaBitSize::Bit2048 => 2048, + }; + let private_key = rsa::RsaPrivateKey::new(&mut rng, bit_size) + .map_err(|_| RsaCryptionError::InvalidPublicKey)?; + let public_key = rsa::RsaPublicKey::from(&private_key); + let signing_key = rsa::pkcs1v15::SigningKey::::new(private_key.clone()); + let verify_key = signing_key.verifying_key(); + Ok(Self { + private_key: Some(private_key), + public_key: Some(public_key), + signing_key: Some(signing_key), + verifying_key: Some(verify_key), + }) + } + + /// 从字节数组中加载私钥,如果加载失败,则返回错误。 + /// 私钥加载成功后,公钥、签名私钥和签名公钥也会被同时自动生成。 + /// + /// - `key`:私钥内容。 + pub fn load_binary_private_key>( + &mut self, + key: T, + ) -> Result<(), RsaCryptionError> { + let private_key = load_binary_private_key(key.as_ref())?; + let public_key = rsa::RsaPublicKey::from(&private_key); + let signing_key = rsa::pkcs1v15::SigningKey::::new(private_key.clone()); + let verify_key = signing_key.verifying_key(); + self.private_key = Some(private_key); + self.public_key = Some(public_key); + self.signing_key = Some(signing_key); + self.verifying_key = Some(verify_key); + Ok(()) + } + + /// 从文本中加载私钥,如果加载失败,则返回错误。 + /// 私钥加载成功后,公钥、签名私钥和签名公钥也会被同时自动生成。 + /// + /// - `pem`:私钥内容。 + pub fn load_text_private_key(&mut self, pem: &str) -> Result<(), RsaCryptionError> { + let private_key = load_text_private_key(pem)?; + let public_key = rsa::RsaPublicKey::from(&private_key); + let signing_key = rsa::pkcs1v15::SigningKey::::new(private_key.clone()); + let verify_key = signing_key.verifying_key(); + self.private_key = Some(private_key); + self.public_key = Some(public_key); + self.signing_key = Some(signing_key); + self.verifying_key = Some(verify_key); + Ok(()) + } + + /// 从字节数组中加载公钥,如果加载失败,则返回错误。 + /// 公钥加载成功后,签名公钥也会被同时自动生成。私钥与签名私钥会被置为`None`。 + /// ! 没有私钥的情况下,无法对内容进行解密。 + /// + /// - `key`:公钥内容。 + pub fn load_binary_public_key>( + &mut self, + key: T, + ) -> Result<(), RsaCryptionError> { + let public_key = load_binary_public_key(key.as_ref())?; + let verify_key = rsa::pkcs1v15::VerifyingKey::::from(public_key.clone()); + self.private_key = None; + self.public_key = Some(public_key); + self.signing_key = None; + self.verifying_key = Some(verify_key); + Ok(()) + } + + /// 从文本中加载公钥,如果加载失败,则返回错误。 + /// 公钥加载成功后,签名公钥也会被同时自动生成。私钥与签名私钥会被置为`None`。 + /// ! 没有私钥的情况下,无法对内容进行解密。 + /// + /// - `pem`:公钥内容。 + pub fn load_text_public_key(&mut self, pem: &str) -> Result<(), RsaCryptionError> { + let public_key = load_text_public_key(pem)?; + let verify_key = rsa::pkcs1v15::VerifyingKey::::from(public_key.clone()); + self.private_key = None; + self.public_key = Some(public_key); + self.signing_key = None; + self.verifying_key = Some(verify_key); + Ok(()) + } + + /// 对指定内容进行加密,返回加密后的内容。 + /// + /// - `data`:待加密的内容。 + pub fn encrypt>(&self, data: T) -> Result, RsaCryptionError> { + if self.public_key.is_none() { + return Err(RsaCryptionError::PublicKeyRequired); + } + let mut rng = rand::thread_rng(); + let encrypted_data = self + .public_key + .as_ref() + .unwrap() + .encrypt(&mut rng, Pkcs1v15Encrypt, data.as_ref()) + .map_err(|e| RsaCryptionError::CryptionFailed(e))?; + Ok(encrypted_data) + } + + /// 对指定内容进行解密,返回解密后的内容。如果没有私钥,则返回错误。 + /// + /// - `data`:待解密的内容。 + pub fn decrypt>(&self, data: T) -> Result, RsaCryptionError> { + if self.private_key.is_none() { + return Err(RsaCryptionError::PrivateKeyRequired); + } + let decrypted_data = self + .private_key + .as_ref() + .unwrap() + .decrypt(Pkcs1v15Encrypt, data.as_ref()) + .map_err(|e| RsaCryptionError::CryptionFailed(e))?; + Ok(decrypted_data) + } + + /// 对指定内容进行签名,返回签名后的内容。如果没有签名私钥,则返回错误。 + /// + /// - `data`:待签名的内容。 + pub fn sign>(&self, data: T) -> Result, RsaCryptionError> { + if self.signing_key.is_none() { + return Err(RsaCryptionError::SigningKeyRequired); + } + let mut rng = rand::thread_rng(); + let sign_data = self + .signing_key + .as_ref() + .unwrap() + .sign_with_rng(&mut rng, data.as_ref()) + .to_vec(); + Ok(sign_data) + } + + /// 对指定内容和签名进行验证,如果验证失败,则返回错误。 + /// + /// - `signature`:签名内容。 + /// - `data`:待验证的内容。 + pub fn verify>(&self, signature: T, data: T) -> Result<(), RsaCryptionError> { + if self.verifying_key.is_none() { + return Err(RsaCryptionError::VerifyingKeyRequired); + } + let signature = rsa::pkcs1v15::Signature::try_from(signature.as_ref()) + .map_err(|_| RsaCryptionError::UnableToLoadSignature)?; + self.verifying_key + .as_ref() + .unwrap() + .verify(data.as_ref(), &signature) + .map_err(|_| RsaCryptionError::VerificationFailed)?; + Ok(()) + } + + /// 以字节数组方式导出私钥,如果没有私钥,则返回错误。 + pub fn export_private_key_binary(&self) -> Result, RsaCryptionError> { + if self.private_key.is_none() { + return Err(RsaCryptionError::PrivateKeyRequired); + } + let doc = self + .private_key + .as_ref() + .unwrap() + .to_pkcs1_der() + .map_err(|_| RsaCryptionError::UnableToExportPrivateKey)?; + Ok(doc.as_bytes().to_vec()) + } + + /// 以PEM文本方式导出私钥,如果没有私钥,则返回错误。 + pub fn export_private_key_pem(&self) -> Result { + if self.private_key.is_none() { + return Err(RsaCryptionError::PrivateKeyRequired); + } + let doc = self + .private_key + .as_ref() + .unwrap() + .to_pkcs1_pem(rsa::pkcs1::LineEnding::CRLF) + .map_err(|_| RsaCryptionError::UnableToExportPrivateKey)?; + Ok(doc.to_string()) + } + + /// 以字节数组的方式导出公钥,如果没有公钥,则返回错误。 + pub fn export_public_key_binary(&self) -> Result, RsaCryptionError> { + if self.public_key.is_none() { + return Err(RsaCryptionError::PublicKeyRequired); + } + let doc = self + .public_key + .as_ref() + .unwrap() + .to_pkcs1_der() + .map_err(|_| RsaCryptionError::UnableToExportPublicKey)?; + Ok(doc.into_vec()) + } + + /// 以PEM文本方式导出公钥,如果没有公钥,则返回错误。 + pub fn export_public_key_pem(&self) -> Result { + if self.public_key.is_none() { + return Err(RsaCryptionError::PublicKeyRequired); + } + let doc = self + .public_key + .as_ref() + .unwrap() + .to_pkcs1_pem(rsa::pkcs1::LineEnding::CRLF) + .map_err(|_| RsaCryptionError::UnableToExportPublicKey)?; + Ok(doc) + } +}