Skip to content

Commit

Permalink
Fix #2: swap argument order for verify and verify_and_update
Browse files Browse the repository at this point in the history
  • Loading branch information
frankie567 committed Mar 11, 2024
1 parent 2a847c1 commit ec2bc72
Show file tree
Hide file tree
Showing 9 changed files with 24 additions and 20 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ from pwdlib import PasswordHash

password_hash = PasswordHash.recommended()
hash = password_hash.hash("herminetincture")
password_hash.verify(hash, "herminetincture") # True
password_hash.verify("herminetincture", hash) # True
```

## Why `pwdlib`?
Expand Down
4 changes: 2 additions & 2 deletions docs/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ The resulting string is a hash generated from the **current algorithm**, which y
When you want to verify a password corresponds to a hash, use the [`verify`](./reference/pwdlib.md#pwdlib.PasswordHash.verify) method:

```py
valid = password_hash.verify(hash, "herminetincture")
valid = password_hash.verify("herminetincture", hash)
```

Under the hood, it'll check against all the enabled algorithms. It means that if older users still have a hash with a legacy algorithm, we'll still be able to verify it.
Expand All @@ -97,7 +97,7 @@ This is the purpose of the [`verify_and_update`](./reference/pwdlib.md#pwdlib.Pa


```py
valid, updated_hash = password_hash.verify_and_update(hash, "herminetincture")
valid, updated_hash = password_hash.verify_and_update("herminetincture", hash)
```

If the hash needs to be updated, `updated_hash` will be a string. Otherwise, it's `None`. Then, don't forget to update it in your database.
Expand Down
18 changes: 9 additions & 9 deletions pwdlib/_hash.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,14 @@ def hash(
return self.current_hasher.hash(password, salt=salt)

def verify(
self, hash: typing.Union[str, bytes], password: typing.Union[str, bytes]
self, password: typing.Union[str, bytes], hash: typing.Union[str, bytes]
) -> bool:
"""
Verifies if a password matches a given hash.
Args:
hash: The hash to be verified.
password: The password to be checked.
hash: The hash to be verified.
Returns:
True if the password matches the hash, False otherwise.
Expand All @@ -76,26 +76,26 @@ def verify(
exceptions.UnknownHashError: If the hash is not recognized by any of the hashers.
Examples:
>>> password_hash.verify(hash, "herminetincture")
>>> password_hash.verify("herminetincture", hash)
True
>>> password_hash.verify(hash, "INVALID_PASSWORD")
>>> password_hash.verify("INVALID_PASSWORD", hash)
False
"""
for hasher in self.hashers:
if hasher.identify(hash):
return hasher.verify(hash, password)
return hasher.verify(password, hash)
raise exceptions.UnknownHashError(hash)

def verify_and_update(
self, hash: typing.Union[str, bytes], password: typing.Union[str, bytes]
self, password: typing.Union[str, bytes], hash: typing.Union[str, bytes]
) -> typing.Tuple[bool, typing.Union[str, None]]:
"""
Verifies if a password matches a given hash and updates the hash if necessary.
Args:
hash: The hash to be verified.
password: The password to be checked.
hash: The hash to be verified.
Returns:
A tuple containing a boolean indicating if the password matches the hash,
Expand All @@ -105,11 +105,11 @@ def verify_and_update(
exceptions.UnknownHashError: If the hash is not recognized by any of the hashers.
Examples:
>>> valid, updated_hash = password_hash.verify_and_update(hash, "herminetincture")
>>> valid, updated_hash = password_hash.verify_and_update("herminetincture", hash)
"""
for hasher in self.hashers:
if hasher.identify(hash):
if not hasher.verify(hash, password):
if not hasher.verify(password, hash):
return False, None
else:
updated_hash: typing.Union[str, None] = None
Expand Down
4 changes: 3 additions & 1 deletion pwdlib/hashers/argon2.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ def hash(
return self._hasher.hash(password, salt=salt)

def verify(
self, hash: typing.Union[str, bytes], password: typing.Union[str, bytes]
self,
password: typing.Union[str, bytes],
hash: typing.Union[str, bytes],
) -> bool:
try:
return self._hasher.verify(hash, password)
Expand Down
4 changes: 3 additions & 1 deletion pwdlib/hashers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ def hash(
...

def verify(
self, hash: typing.Union[str, bytes], password: typing.Union[str, bytes]
self,
password: typing.Union[str, bytes],
hash: typing.Union[str, bytes],
) -> bool:
...

Expand Down
2 changes: 1 addition & 1 deletion pwdlib/hashers/bcrypt.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def hash(
return ensure_str(bcrypt.hashpw(ensure_bytes(password), salt))

def verify(
self, hash: typing.Union[str, bytes], password: typing.Union[str, bytes]
self, password: typing.Union[str, bytes], hash: typing.Union[str, bytes]
) -> bool:
return bcrypt.checkpw(ensure_bytes(password), ensure_bytes(hash))

Expand Down
2 changes: 1 addition & 1 deletion tests/hashers/test_argon2.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@ def test_verify(
result: bool,
argon2_hasher: Argon2Hasher,
) -> None:
assert argon2_hasher.verify(hash, password) == result
assert argon2_hasher.verify(password, hash) == result
2 changes: 1 addition & 1 deletion tests/hashers/test_bcrypt.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def test_verify(
result: bool,
bcrypt_hasher: BcryptHasher,
) -> None:
assert bcrypt_hasher.verify(hash, password) == result
assert bcrypt_hasher.verify(password, hash) == result


def test_check_needs_rehash(bcrypt_hasher: BcryptHasher) -> None:
Expand Down
6 changes: 3 additions & 3 deletions tests/test_hash.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def test_verify(
result: bool,
password_hash: PasswordHash,
) -> None:
assert password_hash.verify(hash, password) == result
assert password_hash.verify(password, hash) == result


def test_verify_unknown_hash(password_hash: PasswordHash) -> None:
Expand All @@ -71,7 +71,7 @@ def test_verify_and_update(
has_updated_hash: bool,
password_hash: PasswordHash,
) -> None:
valid, updated_hash = password_hash.verify_and_update(hash, password)
valid, updated_hash = password_hash.verify_and_update(password, hash)
assert valid == result
assert updated_hash is not None if has_updated_hash else updated_hash is None
if updated_hash is not None:
Expand All @@ -80,4 +80,4 @@ def test_verify_and_update(

def test_verify_and_update_unknown_hash(password_hash: PasswordHash) -> None:
with pytest.raises(exceptions.UnknownHashError):
password_hash.verify_and_update("INVALID_HASH", _PASSWORD)
password_hash.verify_and_update(_PASSWORD, "INVALID_HASH")

0 comments on commit ec2bc72

Please sign in to comment.