mirror of
https://github.com/danbulant/Portfolio
synced 2026-06-06 16:20:08 +00:00
feat: convert crypto to our service error
This commit is contained in:
parent
98c59694a7
commit
e1ee5b796a
2 changed files with 58 additions and 26 deletions
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue