This commit is contained in:
Jussi 2024-11-09 14:06:34 +02:00
commit abb3eab559
16 changed files with 1035 additions and 0 deletions

71
native/argon2/src/lib.rs Normal file
View file

@ -0,0 +1,71 @@
use argon2::Algorithm;
use argon2::Version;
use argon2::{
password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
Argon2, Params,
};
use rand::rngs::OsRng;
use rustler::Error;
const MIN_PASSWORD_LENGTH: usize = 8;
#[derive(Debug)]
enum ConfigType {
Owasp,
Strong,
TestUnsafe,
}
impl ConfigType {
fn params(&self) -> Params {
match self {
ConfigType::Owasp => Params::new(19456, 2, 1, None).expect("Invalid OWASP config"),
ConfigType::Strong => Params::new(65540, 3, 4, None).expect("Invalid strong config"),
ConfigType::TestUnsafe => Params::new(1024, 1, 1, None).expect("Invalid test config"),
}
}
}
#[rustler::nif]
fn hash_password(password: String, config_type: Option<String>) -> Result<String, Error> {
if password.len() < MIN_PASSWORD_LENGTH {
return Err(Error::Term(Box::new(format!(
"Password must be at least {} characters long",
MIN_PASSWORD_LENGTH
))));
}
let salt = SaltString::generate(&mut OsRng);
let config_type = match config_type.as_deref() {
Some("strong") => ConfigType::Strong,
Some("test_unsafe") => ConfigType::TestUnsafe,
_ => ConfigType::Owasp,
};
let argon2 = Argon2::new(Algorithm::Argon2i, Version::V0x13, config_type.params());
argon2
.hash_password(password.as_bytes(), &salt)
.map(|hash| hash.to_string())
.map_err(|e| Error::Term(Box::new(format!("Hashing error: {}", e))))
}
#[rustler::nif]
fn verify_password(password: String, hash: String) -> Result<bool, Error> {
if password.len() < MIN_PASSWORD_LENGTH {
return Err(Error::Term(Box::new(format!(
"Password must be at least {} characters long",
MIN_PASSWORD_LENGTH
))));
}
let parsed_hash = PasswordHash::new(&hash)
.map_err(|e| Error::Term(Box::new(format!("Invalid hash format: {}", e))))?;
Ok(Argon2::default()
.verify_password(password.as_bytes(), &parsed_hash)
.is_ok())
}
rustler::init!("Elixir.Argon2.Native");