Skip to content

Commit 41af00c

Browse files
committed
Feat: changed hashing algo from sha3 to aragon2
1 parent 97f774c commit 41af00c

File tree

4 files changed

+35
-11
lines changed

4 files changed

+35
-11
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- Add migration script here
2+
ALTER TABLE users ADD COLUMN salt TEXT NOT NULL;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- Add migration script here
2+
ALTER TABLE users DROP COLUMN salt;

src/routes/newsletters.rs

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use actix_web::http::header::{HeaderMap, HeaderValue};
33
use actix_web::http::{header, StatusCode};
44
use actix_web::{web, HttpRequest, HttpResponse, ResponseError};
55
use anyhow::Context;
6+
use argon2::{Algorithm, Argon2, Params, PasswordHash, PasswordVerifier, Version};
67
use secrecy::{ExposeSecret, Secret};
78
use sha3::Digest;
89
use sqlx::PgPool;
@@ -152,21 +153,40 @@ async fn validate_credentials(
152153
credentials: Credentials,
153154
pool: &PgPool,
154155
) -> Result<uuid::Uuid, PublishError> {
155-
let password_hash = sha3::Sha3_256::digest(credentials.password.expose_secret().as_bytes());
156-
let password_hash = format!("{:x}", password_hash);
157-
158-
let user_id: Option<_> = sqlx::query!(
159-
r#"SELECT user_id FROM users WHERE username = $1 AND password_hash = $2"#,
156+
let hasher = Argon2::new(
157+
Algorithm::Argon2id,
158+
Version::V0x13,
159+
Params::new(15000, 2, 1, None)
160+
.context("Failed to build Argon2 params")
161+
.map_err(PublishError::UnexpectedError)?,
162+
);
163+
164+
let row: Option<_> = sqlx::query!(
165+
r#"SELECT user_id, password_hash, salt FROM users WHERE username = $1"#,
160166
credentials.username,
161-
password_hash,
162167
)
163168
.fetch_optional(pool)
164169
.await
165170
.context("Failed to perform the query to validate auth credentials")
166171
.map_err(PublishError::UnexpectedError)?;
167172

168-
user_id
169-
.map(|row| row.user_id)
170-
.ok_or_else(|| anyhow::anyhow!("Invalid username or password"))
171-
.map_err(PublishError::AuthError)
173+
let (expected_password_hash, user_id, salt) = match row {
174+
Some(row) => (row.password_hash, row.user_id, row.salt),
175+
None => {
176+
return Err(PublishError::AuthError(anyhow::anyhow!(
177+
"Invalid username or password"
178+
)))
179+
}
180+
};
181+
182+
let expected_password_hash = PasswordHash::new(&expected_password_hash)
183+
.context("Failed to parse hash in PHC string format")
184+
.map_err(PublishError::UnexpectedError)?;
185+
186+
Argon2::default().verify_password(
187+
credentials.password.expose_secret().as_bytes(),
188+
&expected_password_hash,
189+
).context("Failed to verify password").map_err(PublishError::UnexpectedError)?;
190+
191+
Ok(user_id)
172192
}

tests/api/helpers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ pub async fn spawn_app() -> TestApp {
149149
test_user: TestUser::generate(),
150150
};
151151

152-
test_app.test_user.store(&test_app.db_pool).await;
152+
test_app.test_user.store(&test_app.db_pool).await;
153153
test_app
154154
}
155155

0 commit comments

Comments
 (0)