From b6f1c88203ed3c58f7f66776b13940c227bd2c1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Mon, 12 Feb 2024 18:25:44 +0100 Subject: [PATCH] Add Argon2 parameters --- docs/reference/pwdlib.exceptions.md | 2 +- docs/reference/pwdlib.hashers.md | 11 +++++++++++ mkdocs.yml | 1 + pwdlib/hashers/argon2.py | 29 +++++++++++++++++++++++++++-- pwdlib/hashers/base.py | 8 ++++---- pwdlib/hashers/bcrypt.py | 5 +++++ 6 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 docs/reference/pwdlib.hashers.md diff --git a/docs/reference/pwdlib.exceptions.md b/docs/reference/pwdlib.exceptions.md index 1644ef6..c630487 100644 --- a/docs/reference/pwdlib.exceptions.md +++ b/docs/reference/pwdlib.exceptions.md @@ -1,4 +1,4 @@ -# Reference +# Reference - Exceptions ::: pwdlib.exceptions options: diff --git a/docs/reference/pwdlib.hashers.md b/docs/reference/pwdlib.hashers.md new file mode 100644 index 0000000..085a1cd --- /dev/null +++ b/docs/reference/pwdlib.hashers.md @@ -0,0 +1,11 @@ +# Reference - Hashers + +::: pwdlib.hashers.argon2 + options: + show_root_heading: true + show_source: false + +::: pwdlib.hashers.bcrypt + options: + show_root_heading: true + show_source: false diff --git a/mkdocs.yml b/mkdocs.yml index 3f20869..3aae323 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -63,3 +63,4 @@ nav: - Reference: - pwdlib: reference/pwdlib.md - pwdlib.exceptions: reference/pwdlib.exceptions.md + - pwdlib.hashers: reference/pwdlib.hashers.md diff --git a/pwdlib/hashers/argon2.py b/pwdlib/hashers/argon2.py index f1bc593..9bb8088 100644 --- a/pwdlib/hashers/argon2.py +++ b/pwdlib/hashers/argon2.py @@ -12,8 +12,33 @@ class Argon2Hasher(HasherProtocol): - def __init__(self) -> None: - self._hasher = PasswordHasher() # TODO: handle parameters + def __init__( + self, + time_cost: int = argon2.DEFAULT_TIME_COST, + memory_cost: int = argon2.DEFAULT_MEMORY_COST, + parallelism: int = argon2.DEFAULT_PARALLELISM, + hash_len: int = argon2.DEFAULT_HASH_LENGTH, + salt_len: int = argon2.DEFAULT_RANDOM_SALT_LENGTH, + type: argon2.Type = argon2.Type.ID, + ) -> None: + """ + + Args: + time_cost: Defines the amount of computation realized and + therefore the execution time, given in number of iterations. + memory_cost: Defines the memory usage, given in kibibytes. + parallelism: Defines the number of parallel threads (*changes* + the resulting hash value). + hash_len: Length of the hash in bytes. + salt_len: Length of random salt to be generated for each + password. + type: Argon2 type to use. Only change for interoperability + with legacy systems. + + """ + self._hasher = PasswordHasher( + time_cost, memory_cost, parallelism, hash_len, salt_len, "utf-8", type + ) @classmethod def identify(cls, hash: typing.Union[str, bytes]) -> bool: diff --git a/pwdlib/hashers/base.py b/pwdlib/hashers/base.py index cd21167..21759cd 100644 --- a/pwdlib/hashers/base.py +++ b/pwdlib/hashers/base.py @@ -1,12 +1,12 @@ import typing -def ensure_str(v: typing.Union[str, bytes]) -> str: - return v.decode("utf-8") if isinstance(v, bytes) else typing.cast(str, v) +def ensure_str(v: typing.Union[str, bytes], *, encoding: str = "utf-8") -> str: + return v.decode(encoding) if isinstance(v, bytes) else typing.cast(str, v) -def ensure_bytes(v: typing.Union[str, bytes]) -> bytes: - return v.encode("utf-8") if isinstance(v, str) else v +def ensure_bytes(v: typing.Union[str, bytes], *, encoding: str = "utf-8") -> bytes: + return v.encode(encoding) if isinstance(v, str) else v class HasherProtocol(typing.Protocol): diff --git a/pwdlib/hashers/bcrypt.py b/pwdlib/hashers/bcrypt.py index d60a4bc..6861cae 100644 --- a/pwdlib/hashers/bcrypt.py +++ b/pwdlib/hashers/bcrypt.py @@ -26,6 +26,11 @@ class BcryptHasher(HasherProtocol): def __init__( self, rounds: int = 12, prefix: typing.Literal["2a", "2b"] = "2b" ) -> None: + """ + Args: + rounds: The number of rounds to use for hashing. + prefix: The prefix to use for hashing. + """ self.rounds = rounds self.prefix = prefix.encode("utf-8")