feat: convert crypto to our service error

This commit is contained in:
EETagent 2022-11-14 14:06:48 +01:00
parent 98c59694a7
commit e1ee5b796a
2 changed files with 58 additions and 26 deletions

View file

@ -34,9 +34,7 @@ pub fn random_8_char_string() -> String {
s s
} }
pub async fn hash_password( pub async fn hash_password(password_plain_text: String) -> Result<String, ServiceError> {
password_plain_text: String,
) -> Result<String, Box<dyn std::error::Error>> {
let argon_config = Argon2::new( let argon_config = Argon2::new(
argon2::Algorithm::Argon2i, argon2::Algorithm::Argon2i,
argon2::Version::V0x13, argon2::Version::V0x13,
@ -56,13 +54,13 @@ pub async fn hash_password(
let hash_string = hash.await??; let hash_string = hash.await??;
return Ok(hash_string); Ok(hash_string)
} }
pub async fn verify_password( pub async fn verify_password(
password_plaint_text: String, password_plaint_text: String,
hash: String, hash: String,
) -> Result<bool, Box<dyn std::error::Error>> { ) -> Result<bool, ServiceError> {
let argon_config = Argon2::new( let argon_config = Argon2::new(
argon2::Algorithm::Argon2i, argon2::Algorithm::Argon2i,
argon2::Version::V0x13, argon2::Version::V0x13,
@ -106,7 +104,7 @@ fn convert_key_aes256(key: &str) -> Vec<u8> {
pub async fn encrypt_password( pub async fn encrypt_password(
password_plain_text: String, password_plain_text: String,
key: String, key: String,
) -> Result<String, Box<dyn std::error::Error>> { ) -> Result<String, ServiceError> {
let hash = tokio::task::spawn_blocking(move || { let hash = tokio::task::spawn_blocking(move || {
let aes_key_nonce = convert_key_aes256(&key); let aes_key_nonce = convert_key_aes256(&key);
@ -127,7 +125,7 @@ pub async fn encrypt_password(
pub async fn decrypt_password( pub async fn decrypt_password(
password_cipher_text: String, password_cipher_text: String,
key: String, key: String,
) -> Result<String, Box<dyn std::error::Error>> { ) -> Result<String, ServiceError> {
let input = base64::decode(password_cipher_text).unwrap(); let input = base64::decode(password_cipher_text).unwrap();
let plain = tokio::task::spawn_blocking(move || { let plain = tokio::task::spawn_blocking(move || {
let aes_key_nonce = convert_key_aes256(&key); let aes_key_nonce = convert_key_aes256(&key);
@ -148,7 +146,7 @@ pub async fn decrypt_password(
pub async fn encrypt_password_age( pub async fn encrypt_password_age(
password_plain_text: &str, password_plain_text: &str,
key: &str, key: &str,
) -> Result<String, age::EncryptError> { ) -> Result<String, ServiceError> {
let encryptor = age::Encryptor::with_user_passphrase(age::secrecy::Secret::new(key.to_owned())); let encryptor = age::Encryptor::with_user_passphrase(age::secrecy::Secret::new(key.to_owned()));
let mut encrypt_buffer = Vec::new(); let mut encrypt_buffer = Vec::new();
@ -169,7 +167,7 @@ pub async fn encrypt_password_age(
pub async fn decrypt_password_age( pub async fn decrypt_password_age(
password_encrypted: &str, password_encrypted: &str,
key: &str, key: &str,
) -> Result<String, Box<dyn std::error::Error>> { ) -> Result<String, ServiceError> {
let encrypted = base64::decode(password_encrypted)?; let encrypted = base64::decode(password_encrypted)?;
let decryptor = match age::Decryptor::new_async(&encrypted[..]).await? { let decryptor = match age::Decryptor::new_async(&encrypted[..]).await? {
@ -200,7 +198,7 @@ async fn age_encrypt_with_recipients<W: tokio::io::AsyncWrite + Unpin>(
input_buffer: &[u8], input_buffer: &[u8],
output_buffer: &mut W, output_buffer: &mut W,
recipients: &Vec<&str>, recipients: &Vec<&str>,
) -> Result<(), age::EncryptError> { ) -> Result<(), ServiceError> {
let public_keys = recipients let public_keys = recipients
.into_iter() .into_iter()
.map(|recipient| { .map(|recipient| {
@ -233,14 +231,15 @@ async fn age_decrypt_with_private_key<R: tokio::io::AsyncRead + Unpin>(
input_buffer: R, input_buffer: R,
output_buffer: &mut Vec<u8>, output_buffer: &mut Vec<u8>,
key: &str, key: &str,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), ServiceError> {
let decryptor = match age::Decryptor::new_async(input_buffer.compat()).await? { let decryptor = match age::Decryptor::new_async(input_buffer.compat()).await? {
age::Decryptor::Recipients(d) => d, age::Decryptor::Recipients(d) => d,
_ => unreachable!(), _ => unreachable!(),
}; };
let mut decrypt_writer = decryptor.decrypt_async(iter::once( 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?; decrypt_writer.read_to_end(output_buffer).await?;
@ -251,7 +250,7 @@ async fn age_decrypt_with_private_key<R: tokio::io::AsyncRead + Unpin>(
pub async fn encrypt_password_with_recipients( pub async fn encrypt_password_with_recipients(
password_plain_text: &str, password_plain_text: &str,
recipients: &Vec<&str>, recipients: &Vec<&str>,
) -> Result<String, age::EncryptError> { ) -> Result<String, ServiceError> {
let mut encrypt_buffer = Vec::new(); let mut encrypt_buffer = Vec::new();
age_encrypt_with_recipients( age_encrypt_with_recipients(
@ -267,25 +266,22 @@ pub async fn encrypt_password_with_recipients(
pub async fn decrypt_password_with_private_key( pub async fn decrypt_password_with_private_key(
password_encrypted: &str, password_encrypted: &str,
key: &str, key: &str,
) -> Result<String, ServiceError> { // TODO More specific error handling ) -> Result<String, ServiceError> {
let Ok(encrypted) = base64::decode(password_encrypted) else { let encrypted = base64::decode(password_encrypted)?;
return Err(ServiceError::CryptoEncryptFailed);
};
let mut decrypt_buffer = Vec::new(); let mut decrypt_buffer = Vec::new();
if age_decrypt_with_private_key(encrypted.as_slice(), &mut decrypt_buffer, key).await.is_err() { age_decrypt_with_private_key(encrypted.as_slice(), &mut decrypt_buffer, key).await?;
return Err(ServiceError::CryptoDecryptFailed);
};
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<P: AsRef<Path>>( pub async fn encrypt_file_with_recipients<P: AsRef<Path>>(
plain_file_path: P, plain_file_path: P,
cipher_file_path: P, cipher_file_path: P,
recipients: Vec<&str>, recipients: Vec<&str>,
) -> Result<(), age::EncryptError> { ) -> Result<(), ServiceError> {
let mut cipher_file = tokio::fs::File::create(cipher_file_path).await?; let mut cipher_file = tokio::fs::File::create(cipher_file_path).await?;
let mut plain_file = tokio::fs::File::open(plain_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<P: AsRef<Path>>(
tokio::io::AsyncReadExt::read_to_end(&mut plain_file, &mut plain_file_contents).await?; 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<P: AsRef<Path>>( pub async fn decrypt_file_with_private_key<P: AsRef<Path>>(
cipher_file_path: P, cipher_file_path: P,
plain_file_path: P, plain_file_path: P,
key: &str, key: &str,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), ServiceError> {
let cipher_file = tokio::fs::File::open(cipher_file_path).await?; let cipher_file = tokio::fs::File::open(cipher_file_path).await?;
let mut plain_file = tokio::fs::File::create(plain_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<P: AsRef<Path>>(
pub async fn decrypt_file_with_private_key_as_buffer<P: AsRef<Path>>( pub async fn decrypt_file_with_private_key_as_buffer<P: AsRef<Path>>(
cipher_file_path: P, cipher_file_path: P,
key: &str, key: &str,
) -> Result<Vec<u8>, Box<dyn std::error::Error>> { ) -> Result<Vec<u8>, ServiceError> {
let cipher_file = tokio::fs::File::open(cipher_file_path).await?; let cipher_file = tokio::fs::File::open(cipher_file_path).await?;
let mut plain_file = Vec::new(); let mut plain_file = Vec::new();

View file

@ -33,10 +33,30 @@ pub enum ServiceError {
CryptoDecryptFailed, CryptoDecryptFailed,
#[error("Candidate details not set, please contact technical support")] #[error("Candidate details not set, please contact technical support")]
CandidateDetailsNotSet, 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 { impl ServiceError {
// TODO: Převod do thiserror
fn code_and_message(&self) -> (u16, String) { fn code_and_message(&self) -> (u16, String) {
match self { match self {
ServiceError::InvalidApplicationId => (400, "Invalid application id".to_string()), 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::CryptoEncryptFailed => (500, "Crypto encryption failed, please contact technical support".to_string()),
ServiceError::CryptoDecryptFailed => (500, "Crypto decryption 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()), 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()),
} }
} }