mirror of
https://gitlab.computer.surgery/matrix/grapevine.git
synced 2025-12-17 15:51:23 +01:00
switch to RustCrypto's argon2 crate
This commit is contained in:
parent
60d32ddf48
commit
aa4cd8b1e1
6 changed files with 58 additions and 58 deletions
58
Cargo.lock
generated
58
Cargo.lock
generated
|
|
@ -57,16 +57,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
|
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayref"
|
name = "argon2"
|
||||||
version = "0.3.7"
|
version = "0.5.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545"
|
checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072"
|
||||||
|
dependencies = [
|
||||||
[[package]]
|
"base64ct",
|
||||||
name = "arrayvec"
|
"blake2",
|
||||||
version = "0.7.4"
|
"cpufeatures",
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
"password-hash",
|
||||||
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "as_variant"
|
name = "as_variant"
|
||||||
|
|
@ -345,14 +345,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "blake2b_simd"
|
name = "blake2"
|
||||||
version = "1.0.2"
|
version = "0.10.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780"
|
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayref",
|
"digest",
|
||||||
"arrayvec",
|
|
||||||
"constant_time_eq",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -498,12 +496,6 @@ version = "0.2.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6051f239ecec86fde3410901ab7860d458d160371533842974fc61f96d15879b"
|
checksum = "6051f239ecec86fde3410901ab7860d458d160371533842974fc61f96d15879b"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "constant_time_eq"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation"
|
name = "core-foundation"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
|
|
@ -852,6 +844,7 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||||
name = "grapevine"
|
name = "grapevine"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"argon2",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum 0.7.5",
|
"axum 0.7.5",
|
||||||
"axum-extra",
|
"axum-extra",
|
||||||
|
|
@ -887,7 +880,6 @@ dependencies = [
|
||||||
"ring",
|
"ring",
|
||||||
"ruma",
|
"ruma",
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
"rust-argon2",
|
|
||||||
"rust-rocksdb",
|
"rust-rocksdb",
|
||||||
"sd-notify",
|
"sd-notify",
|
||||||
"serde",
|
"serde",
|
||||||
|
|
@ -1750,6 +1742,17 @@ dependencies = [
|
||||||
"windows-targets 0.52.5",
|
"windows-targets 0.52.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "password-hash"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
|
||||||
|
dependencies = [
|
||||||
|
"base64ct",
|
||||||
|
"rand_core",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pear"
|
name = "pear"
|
||||||
version = "0.2.9"
|
version = "0.2.9"
|
||||||
|
|
@ -2373,17 +2376,6 @@ dependencies = [
|
||||||
"smallvec",
|
"smallvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rust-argon2"
|
|
||||||
version = "2.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9d9848531d60c9cbbcf9d166c885316c24bc0e2a9d3eba0956bb6cbbd79bc6e8"
|
|
||||||
dependencies = [
|
|
||||||
"base64 0.21.7",
|
|
||||||
"blake2b_simd",
|
|
||||||
"constant_time_eq",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rust-librocksdb-sys"
|
name = "rust-librocksdb-sys"
|
||||||
version = "0.22.0+9.2.1"
|
version = "0.22.0+9.2.1"
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ workspace = true
|
||||||
|
|
||||||
# Keep sorted
|
# Keep sorted
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
argon2 = "0.5.3"
|
||||||
async-trait = "0.1.80"
|
async-trait = "0.1.80"
|
||||||
axum = { version = "0.7.5", default-features = false, features = ["form", "http1", "http2", "json", "matched-path", "tracing"] }
|
axum = { version = "0.7.5", default-features = false, features = ["form", "http1", "http2", "json", "matched-path", "tracing"] }
|
||||||
axum-extra = { version = "0.9.3", features = ["typed-header"] }
|
axum-extra = { version = "0.9.3", features = ["typed-header"] }
|
||||||
|
|
@ -122,7 +123,6 @@ ring = "0.17.8"
|
||||||
rocksdb = { package = "rust-rocksdb", version = "0.26.0", features = ["lz4", "multi-threaded-cf", "zstd"], optional = true }
|
rocksdb = { package = "rust-rocksdb", version = "0.26.0", features = ["lz4", "multi-threaded-cf", "zstd"], optional = true }
|
||||||
ruma = { git = "https://github.com/ruma/ruma", branch = "main", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "server-util", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] }
|
ruma = { git = "https://github.com/ruma/ruma", branch = "main", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "server-util", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] }
|
||||||
rusqlite = { version = "0.31.0", optional = true, features = ["bundled"] }
|
rusqlite = { version = "0.31.0", optional = true, features = ["bundled"] }
|
||||||
rust-argon2 = "2.1.0"
|
|
||||||
sd-notify = { version = "0.4.1", optional = true }
|
sd-notify = { version = "0.4.1", optional = true }
|
||||||
serde = { version = "1.0.202", features = ["rc"] }
|
serde = { version = "1.0.202", features = ["rc"] }
|
||||||
serde_html_form = "0.2.6"
|
serde_html_form = "0.2.6"
|
||||||
|
|
|
||||||
|
|
@ -113,11 +113,7 @@ pub(crate) async fn login_route(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let hash_matches =
|
if !utils::verify_password_hash(hash, password) {
|
||||||
argon2::verify_encoded(&hash, password.as_bytes())
|
|
||||||
.unwrap_or(false);
|
|
||||||
|
|
||||||
if !hash_matches {
|
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
ErrorKind::forbidden(),
|
ErrorKind::forbidden(),
|
||||||
"Wrong username or password.",
|
"Wrong username or password.",
|
||||||
|
|
|
||||||
|
|
@ -584,10 +584,9 @@ impl KeyValueDatabase {
|
||||||
for (userid, password) in db.userid_password.iter() {
|
for (userid, password) in db.userid_password.iter() {
|
||||||
let password = utils::string_from_bytes(&password);
|
let password = utils::string_from_bytes(&password);
|
||||||
|
|
||||||
let empty_hashed_password =
|
let empty_hashed_password = password
|
||||||
password.map_or(false, |password| {
|
.map_or(false, |password| {
|
||||||
argon2::verify_encoded(&password, b"")
|
utils::verify_password_hash("", password)
|
||||||
.unwrap_or(false)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if empty_hashed_password {
|
if empty_hashed_password {
|
||||||
|
|
|
||||||
|
|
@ -87,11 +87,7 @@ impl Service {
|
||||||
|
|
||||||
// Check if password is correct
|
// Check if password is correct
|
||||||
if let Some(hash) = services().users.password_hash(&user_id)? {
|
if let Some(hash) = services().users.password_hash(&user_id)? {
|
||||||
let hash_matches =
|
if !utils::verify_password_hash(hash, password) {
|
||||||
argon2::verify_encoded(&hash, password.as_bytes())
|
|
||||||
.unwrap_or(false);
|
|
||||||
|
|
||||||
if !hash_matches {
|
|
||||||
uiaainfo.auth_error =
|
uiaainfo.auth_error =
|
||||||
Some(ruma::api::client::error::StandardErrorBody {
|
Some(ruma::api::client::error::StandardErrorBody {
|
||||||
kind: ErrorKind::forbidden(),
|
kind: ErrorKind::forbidden(),
|
||||||
|
|
|
||||||
37
src/utils.rs
37
src/utils.rs
|
|
@ -7,9 +7,9 @@ use std::{
|
||||||
time::{SystemTime, UNIX_EPOCH},
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
};
|
};
|
||||||
|
|
||||||
use argon2::{Config, Variant};
|
use argon2::{password_hash, Argon2, PasswordHasher, PasswordVerifier};
|
||||||
use cmp::Ordering;
|
use cmp::Ordering;
|
||||||
use rand::prelude::*;
|
use rand::{prelude::*, rngs::OsRng};
|
||||||
use ring::digest;
|
use ring::digest;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
canonical_json::try_from_json_map, CanonicalJsonError, CanonicalJsonObject,
|
canonical_json::try_from_json_map, CanonicalJsonError, CanonicalJsonObject,
|
||||||
|
|
@ -72,16 +72,33 @@ pub(crate) fn random_string(length: usize) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate a new hash for the given password
|
/// Calculate a new hash for the given password
|
||||||
pub(crate) fn calculate_password_hash(
|
pub(crate) fn calculate_password_hash<B>(
|
||||||
password: &str,
|
password: B,
|
||||||
) -> Result<String, argon2::Error> {
|
) -> Result<password_hash::PasswordHashString, password_hash::Error>
|
||||||
let hashing_config = Config {
|
where
|
||||||
variant: Variant::Argon2id,
|
B: AsRef<[u8]>,
|
||||||
..Default::default()
|
{
|
||||||
|
Argon2::default()
|
||||||
|
.hash_password(
|
||||||
|
password.as_ref(),
|
||||||
|
&password_hash::SaltString::generate(&mut OsRng),
|
||||||
|
)
|
||||||
|
.map(|x| x.serialize())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compare a password to a hash
|
||||||
|
///
|
||||||
|
/// Returns `true` if the password matches the hash, `false` otherwise.
|
||||||
|
pub(crate) fn verify_password_hash<S, B>(hash: S, password: B) -> bool
|
||||||
|
where
|
||||||
|
S: AsRef<str>,
|
||||||
|
B: AsRef<[u8]>,
|
||||||
|
{
|
||||||
|
let Ok(hash) = password_hash::PasswordHash::new(hash.as_ref()) else {
|
||||||
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
let salt = random_string(32);
|
Argon2::default().verify_password(password.as_ref(), &hash).is_ok()
|
||||||
argon2::hash_encoded(password.as_bytes(), salt.as_bytes(), &hashing_config)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(keys))]
|
#[tracing::instrument(skip(keys))]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue