Skip to content

Commit

Permalink
fixes #917 -- correctly handle a salt that's too short (#918)
Browse files Browse the repository at this point in the history
  • Loading branch information
alex authored Nov 21, 2024
1 parent ad8f19f commit c6c03f7
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 8 deletions.
21 changes: 13 additions & 8 deletions src/_bcrypt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,14 @@ fn hashpw<'p>(
// salt here is not just the salt bytes, but rather an encoded value
// containing a version number, number of rounds, and the salt.
// Should be [prefix, cost, hash]. This logic is copied from `bcrypt`
let raw_parts: Vec<_> = salt
let [raw_version, raw_cost, remainder]: [&[u8]; 3] = salt
.split(|&b| b == b'$')
.filter(|s| !s.is_empty())
.collect();
if raw_parts.len() != 3 {
return Err(pyo3::exceptions::PyValueError::new_err("Invalid salt"));
}
let version = match raw_parts[0] {
.collect::<Vec<_>>()
.try_into()
.map_err(|_| pyo3::exceptions::PyValueError::new_err("Invalid salt"))?;

let version = match raw_version {
b"2y" => bcrypt::Version::TwoY,
b"2b" => bcrypt::Version::TwoB,
b"2a" => bcrypt::Version::TwoA,
Expand All @@ -99,15 +99,20 @@ fn hashpw<'p>(
return Err(pyo3::exceptions::PyValueError::new_err("Invalid salt"));
}
};
let cost = std::str::from_utf8(raw_parts[1])
let cost = std::str::from_utf8(raw_cost)
.map_err(|_| pyo3::exceptions::PyValueError::new_err("Invalid salt"))?
.parse::<u32>()
.map_err(|_| pyo3::exceptions::PyValueError::new_err("Invalid salt"))?;

if remainder.len() < 22 {
return Err(pyo3::exceptions::PyValueError::new_err("Invalid salt"));
}

// The last component can contain either just the salt, or the salt and
// the result hash, depending on if the `salt` value come from `hashpw` or
// `gensalt`.
let raw_salt = BASE64_ENGINE
.decode(&raw_parts[2][..22])
.decode(&remainder[..22])
.map_err(|_| pyo3::exceptions::PyValueError::new_err("Invalid salt"))?
.try_into()
.map_err(|_| pyo3::exceptions::PyValueError::new_err("Invalid salt"))?;
Expand Down
2 changes: 2 additions & 0 deletions tests/test_bcrypt.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ def test_checkpw_bad_salt():
b"password",
b"$2b$3$mdEQPMOtfPX.WGZNXgF66OhmBlOGKEd66SQ7DyJPGucYYmvTJYviy",
)
with pytest.raises(ValueError):
bcrypt.checkpw(b"password", b"$2b$12$incorrect")


def test_checkpw_str_password():
Expand Down

0 comments on commit c6c03f7

Please sign in to comment.