From e1ee5b796ac0c18b56cf6060df62fd29c230a7ab Mon Sep 17 00:00:00 2001 From: EETagent Date: Mon, 14 Nov 2022 14:06:48 +0100 Subject: [PATCH] feat: convert crypto to our service error --- core/src/crypto.rs | 51 +++++++++++++++++++++++----------------------- core/src/error.rs | 33 +++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 26 deletions(-) diff --git a/core/src/crypto.rs b/core/src/crypto.rs index 3270091..8fe0582 100644 --- a/core/src/crypto.rs +++ b/core/src/crypto.rs @@ -34,9 +34,7 @@ pub fn random_8_char_string() -> String { s } -pub async fn hash_password( - password_plain_text: String, -) -> Result> { +pub async fn hash_password(password_plain_text: String) -> Result { let argon_config = Argon2::new( argon2::Algorithm::Argon2i, argon2::Version::V0x13, @@ -56,13 +54,13 @@ pub async fn hash_password( let hash_string = hash.await??; - return Ok(hash_string); + Ok(hash_string) } pub async fn verify_password( password_plaint_text: String, hash: String, -) -> Result> { +) -> Result { let argon_config = Argon2::new( argon2::Algorithm::Argon2i, argon2::Version::V0x13, @@ -106,7 +104,7 @@ fn convert_key_aes256(key: &str) -> Vec { pub async fn encrypt_password( password_plain_text: String, key: String, -) -> Result> { +) -> Result { let hash = tokio::task::spawn_blocking(move || { let aes_key_nonce = convert_key_aes256(&key); @@ -127,7 +125,7 @@ pub async fn encrypt_password( pub async fn decrypt_password( password_cipher_text: String, key: String, -) -> Result> { +) -> Result { let input = base64::decode(password_cipher_text).unwrap(); let plain = tokio::task::spawn_blocking(move || { let aes_key_nonce = convert_key_aes256(&key); @@ -148,7 +146,7 @@ pub async fn decrypt_password( pub async fn encrypt_password_age( password_plain_text: &str, key: &str, -) -> Result { +) -> Result { let encryptor = age::Encryptor::with_user_passphrase(age::secrecy::Secret::new(key.to_owned())); let mut encrypt_buffer = Vec::new(); @@ -169,7 +167,7 @@ pub async fn encrypt_password_age( pub async fn decrypt_password_age( password_encrypted: &str, key: &str, -) -> Result> { +) -> Result { let encrypted = base64::decode(password_encrypted)?; let decryptor = match age::Decryptor::new_async(&encrypted[..]).await? { @@ -200,7 +198,7 @@ async fn age_encrypt_with_recipients( input_buffer: &[u8], output_buffer: &mut W, recipients: &Vec<&str>, -) -> Result<(), age::EncryptError> { +) -> Result<(), ServiceError> { let public_keys = recipients .into_iter() .map(|recipient| { @@ -233,14 +231,15 @@ async fn age_decrypt_with_private_key( input_buffer: R, output_buffer: &mut Vec, key: &str, -) -> Result<(), Box> { +) -> Result<(), ServiceError> { let decryptor = match age::Decryptor::new_async(input_buffer.compat()).await? { age::Decryptor::Recipients(d) => d, _ => unreachable!(), }; let mut decrypt_writer = decryptor.decrypt_async(iter::once( - &age::x25519::Identity::from_str(key)? as &dyn age::Identity, + &age::x25519::Identity::from_str(key).map_err(|e| ServiceError::AgeKeyError(e.to_string()))? + as &dyn age::Identity, ))?; decrypt_writer.read_to_end(output_buffer).await?; @@ -251,7 +250,7 @@ async fn age_decrypt_with_private_key( pub async fn encrypt_password_with_recipients( password_plain_text: &str, recipients: &Vec<&str>, -) -> Result { +) -> Result { let mut encrypt_buffer = Vec::new(); age_encrypt_with_recipients( @@ -267,25 +266,22 @@ pub async fn encrypt_password_with_recipients( pub async fn decrypt_password_with_private_key( password_encrypted: &str, key: &str, -) -> Result { // TODO More specific error handling - let Ok(encrypted) = base64::decode(password_encrypted) else { - return Err(ServiceError::CryptoEncryptFailed); - }; +) -> Result { + let encrypted = base64::decode(password_encrypted)?; let mut decrypt_buffer = Vec::new(); - if age_decrypt_with_private_key(encrypted.as_slice(), &mut decrypt_buffer, key).await.is_err() { - return Err(ServiceError::CryptoDecryptFailed); - }; + age_decrypt_with_private_key(encrypted.as_slice(), &mut decrypt_buffer, key).await?; - String::from_utf8(decrypt_buffer).map_err(|_| ServiceError::CryptoDecryptFailed) + let string = String::from_utf8(decrypt_buffer)?; + Ok(string) } pub async fn encrypt_file_with_recipients>( plain_file_path: P, cipher_file_path: P, recipients: Vec<&str>, -) -> Result<(), age::EncryptError> { +) -> Result<(), ServiceError> { let mut cipher_file = tokio::fs::File::create(cipher_file_path).await?; let mut plain_file = tokio::fs::File::open(plain_file_path).await?; @@ -293,14 +289,19 @@ pub async fn encrypt_file_with_recipients>( tokio::io::AsyncReadExt::read_to_end(&mut plain_file, &mut plain_file_contents).await?; - age_encrypt_with_recipients(plain_file_contents.as_slice(), &mut cipher_file, &recipients).await + age_encrypt_with_recipients( + plain_file_contents.as_slice(), + &mut cipher_file, + &recipients, + ) + .await } pub async fn decrypt_file_with_private_key>( cipher_file_path: P, plain_file_path: P, key: &str, -) -> Result<(), Box> { +) -> Result<(), ServiceError> { let cipher_file = tokio::fs::File::open(cipher_file_path).await?; let mut plain_file = tokio::fs::File::create(plain_file_path).await?; @@ -316,7 +317,7 @@ pub async fn decrypt_file_with_private_key>( pub async fn decrypt_file_with_private_key_as_buffer>( cipher_file_path: P, key: &str, -) -> Result, Box> { +) -> Result, ServiceError> { let cipher_file = tokio::fs::File::open(cipher_file_path).await?; let mut plain_file = Vec::new(); diff --git a/core/src/error.rs b/core/src/error.rs index 2aceac3..3141ac6 100644 --- a/core/src/error.rs +++ b/core/src/error.rs @@ -33,10 +33,30 @@ pub enum ServiceError { CryptoDecryptFailed, #[error("Candidate details not set, please contact technical support")] CandidateDetailsNotSet, - + #[error("Tokio join error")] + TokioJoinError(#[from] tokio::task::JoinError), + #[error("Age encrypt error")] + AgeEncryptError(#[from] age::EncryptError), + #[error("Age decrypt error")] + AgeDecryptError(#[from] age::DecryptError), + #[error("Age key error")] + AgeKeyError(String), + #[error("IO error")] + IOError(#[from] std::io::Error), + #[error("Base64 decode error")] + Base64DecodeError(#[from] base64::DecodeError), + #[error("UTF8 decode error")] + UTF8DecodeError(#[from] std::string::FromUtf8Error), + #[error("Argon config error")] + ArgonConfigError(#[from] argon2::Error), + #[error("Argon hash error")] + ArgonHashError(#[from] argon2::password_hash::Error), + #[error("AES error")] + AesError(#[from] aes_gcm_siv::Error), } impl ServiceError { + // TODO: Převod do thiserror fn code_and_message(&self) -> (u16, String) { match self { ServiceError::InvalidApplicationId => (400, "Invalid application id".to_string()), @@ -54,6 +74,17 @@ impl ServiceError { ServiceError::CryptoEncryptFailed => (500, "Crypto encryption failed, please contact technical support".to_string()), ServiceError::CryptoDecryptFailed => (500, "Crypto decryption failed, please contact technical support".to_string()), ServiceError::CandidateDetailsNotSet => (500, "Candidate details not set, please contact technical support".to_string()), + // TODO: Dodělat hlášky + ServiceError::AgeEncryptError(_) => (500, "Age encrypt error".to_string()), + ServiceError::AgeDecryptError(_) => (500, "Age decrypt error".to_string()), + ServiceError::AgeKeyError(_) => (500, "Age key error".to_string()), + ServiceError::IOError(_) => (500, "IO error".to_string()), + ServiceError::Base64DecodeError(_) => (500, "Base64 decode error".to_string()), + ServiceError::UTF8DecodeError(_) => (500, "UTF8 decode error".to_string()), + ServiceError::ArgonHashError(_) => (500, "Argon hash error".to_string()), + ServiceError::TokioJoinError(_) => (500, "Tokio join error".to_string()), + ServiceError::AesError(_) => (500, "AES error".to_string()), + ServiceError::ArgonConfigError(_) => (500, "Argon config error".to_string()), } }