This commit is contained in:
Hynek Schlawack 2023-11-28 08:56:54 +01:00
parent ecd1b32632
commit c9683325d5
No known key found for this signature in database
GPG Key ID: AE2536227F69F181
6 changed files with 135 additions and 80 deletions

View File

@ -106,16 +106,22 @@ But it's way more comfortable to run it locally and *git* catching avoidable err
## Code
- Obey [PEP 8](https://www.python.org/dev/peps/pep-0008/) and [PEP 257](https://www.python.org/dev/peps/pep-0257/).
We use the `"""`-on-separate-lines style for docstrings:
We use the `"""`-on-separate-lines style for docstrings and [Napoleon](https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html) for parsing them:
```python
def func(x):
def func(x: str, y: bool) -> int:
"""
Do something.
:param str x: A very important parameter.
Parameters:
x: A very important parameter.
:rtype: str
y:
Another important parameter whose description is too long for one
line, therefore it starts on the next line.
Returns:
Something!
"""
```
- If you add or change public APIs, tag the docstring using `.. versionadded:: 16.0.0 WHAT` or `.. versionchanged:: 16.2.0 WHAT`.

View File

@ -18,7 +18,7 @@ Argon2**d**'s strength is the resistance against [timememory trade-offs], whi
Accordingly, Argon2**i** was originally considered the correct choice for password hashing and password-based key derivation.
In practice it turned out that a *combination* of d and i -- that combines their strengths -- is the better choice.
And so Argon2**id** was born and is now considered the *main variant* (and the only variant required by the RFC to be implemented).
And so Argon2**id** was born and is now considered the *main variant* -- and the only variant required by the RFC to be implemented.
## Why “just use bcrypt” Is Not the Best Answer (Anymore)

View File

@ -13,10 +13,10 @@ But since *argon2-cffi* depends on [argon2-cffi-bindings] that vendors Argon2's
The C code is known to compile and work on all common platforms (including x86, ARM, and PPC).
On x86, an [SSE2]-optimized version is used.
If something goes wrong, please try to update your *cffi*, *pip* and *setuptools* packages first:
If something goes wrong, please try to update your *pip* package first:
```console
$ python -Im pip install -U cffi pip setuptools
$ python -Im pip install -U pip
```
Overall this should be the safest bet because *argon2-cffi* has been specifically tested against the vendored version.
@ -25,7 +25,7 @@ Overall this should be the safest bet because *argon2-cffi* has been specificall
### Wheels
Binary [wheels](https://pythonwheels.com) for macOS, Windows, and Linux are provided on [PyPI] by [argon2-cffi-bindings].
With a recent-enough *pip* and *setuptools*, they should be used automatically.
With a recent-enough *pip* they should be used automatically.
### Source Distribution
@ -50,8 +50,12 @@ This approach can lead to problems around your build chain and you can run into
**It is your own responsibility to deal with these risks if you choose this path.**
Available since version 18.1.0.
The `--no-binary` option value changed in 21.2.0 due to the outsourcing of the binary bindings.
:::{versionadded} 18.1.0
:::
:::{versionchanged} 21.2.0
The `--no-binary` option value changed due to the outsourcing of the binary bindings.
:::
## Override Automatic SSE2 Detection
@ -65,7 +69,8 @@ Therefore you can use the `ARGON2_CFFI_USE_SSE2` environment variable to control
- If you set it to `0`, *argon2-cffi* will build **without** SSE2 support.
- If you set it to anything else, it will be ignored and *argon2-cffi* will try to guess.
Available since version 20.1.0.
:::{versionadded} 20.1.0
:::
[argon2-cffi-bindings]: https://github.com/hynek/argon2-cffi-bindings
[cffi environment]: https://cffi.readthedocs.io/en/latest/installation.html

View File

@ -33,27 +33,36 @@ class PasswordHasher:
r"""
High level class to hash passwords with sensible defaults.
Uses Argon2\ **id** by default and always uses a random salt_ for hashing.
But it can verify any type of Argon2 as long as the hash is correctly
encoded.
Uses Argon2\ **id** by default and uses a random salt_ for hashing. But it
can verify any type of Argon2 as long as the hash is correctly encoded.
The reason for this being a class is both for convenience to carry
parameters and to verify the parameters only *once*. Any unnecessary
slowdown when hashing is a tangible advantage for a brute force attacker.
slowdown when hashing is a tangible advantage for a brute-force attacker.
:param int time_cost: Defines the amount of computation realized and
therefore the execution time, given in number of iterations.
:param int memory_cost: Defines the memory usage, given in kibibytes_.
:param int parallelism: Defines the number of parallel threads (*changes*
the resulting hash value).
:param int hash_len: Length of the hash in bytes.
:param int salt_len: Length of random salt to be generated for each
password.
:param str encoding: The Argon2 C library expects bytes. So if
:meth:`hash` or :meth:`verify` are passed a ``str``, it will be
encoded using this encoding.
:param Type type: Argon2 type to use. Only change for interoperability
with legacy systems.
Parameters:
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.
encoding:
The Argon2 C library expects bytes. So if :meth:`hash` or
:meth:`verify` are passed a ``str``, it will be encoded using this
encoding.
type:
Argon2 type to use. Only change for interoperability with legacy
systems.
.. versionadded:: 16.0.0
.. versionchanged:: 18.2.0
@ -114,6 +123,9 @@ class PasswordHasher:
"""
Construct a `PasswordHasher` from *params*.
Returns:
A `PasswordHasher` instance with the parameters from *params*.
.. versionadded:: 21.2.0
"""
ph = cls()
@ -150,7 +162,6 @@ class PasswordHasher:
Hash *password* and return an encoded hash.
Parameters:
password: Password to hash.
salt: If None, a random salt is securely created.
@ -161,11 +172,9 @@ class PasswordHasher:
you are doing.
Raises:
argon2.exceptions.HashingError: If hashing fails.
Returns:
Hashed *password*.
.. versionadded:: 23.1.0 *salt* parameter
@ -198,23 +207,25 @@ class PasswordHasher:
other parsing than the determination of the hash type is done by
*argon2-cffi*.
:param hash: An encoded hash as returned from
:meth:`PasswordHasher.hash`.
:type hash: ``bytes`` or ``str``
Parameters:
hash: An encoded hash as returned from :meth:`PasswordHasher.hash`.
:param password: The password to verify.
:type password: ``bytes`` or ``str``
password: The password to verify.
:raises argon2.exceptions.VerifyMismatchError: If verification fails
because *hash* is not valid for *password*.
:raises argon2.exceptions.VerificationError: If verification fails for
other reasons.
:raises argon2.exceptions.InvalidHashError: If *hash* is so clearly
invalid, that it couldn't be passed to Argon2.
Raises:
argon2.exceptions.VerifyMismatchError:
If verification fails because *hash* is not valid for
*password*.
:return: ``True`` on success, raise
:exc:`~argon2.exceptions.VerificationError` otherwise.
:rtype: bool
argon2.exceptions.VerificationError:
If verification fails for other reasons.
argon2.exceptions.InvalidHashError:
If *hash* is so clearly invalid, that it couldn't be passed to
Argon2.
Returns:
``True`` on success, otherwise an exception is raised.
.. versionchanged:: 16.1.0
Raise :exc:`~argon2.exceptions.VerifyMismatchError` on mismatches
@ -244,7 +255,11 @@ class PasswordHasher:
Therefore it's best practice to check -- and if necessary rehash --
passwords after each successful authentication.
:rtype: bool
Parameters:
hash: An encoded Argon2 password hash.
Returns:
Whether *hash* was created using the instance's parameters.
.. versionadded:: 18.2.0
"""

View File

@ -58,13 +58,20 @@ class Parameters:
See :doc:`parameters` on how to pick them.
:ivar Type type: Hash type.
:ivar int version: Argon2 version.
:ivar int salt_len: Length of the salt in bytes.
:ivar int hash_len: Length of the hash in bytes.
:ivar int time_cost: Time cost in iterations.
:ivar int memory_cost: Memory cost in kibibytes.
:ivar int parallelism: Number of parallel threads.
Attributes:
type: Hash type.
version: Argon2 version.
salt_len: Length of the salt in bytes.
hash_len: Length of the hash in bytes.
time_cost: Time cost in iterations.
memory_cost: Memory cost in kibibytes.
parallelism: Number of parallel threads.
.. versionadded:: 18.2.0
"""
@ -96,9 +103,11 @@ def extract_parameters(hash: str) -> Parameters:
"""
Extract parameters from an encoded *hash*.
:param str params: An encoded Argon2 hash string.
Parameters:
hash: An encoded Argon2 hash string.
:rtype: Parameters
Returns:
The parameters used to create the hash.
.. versionadded:: 18.2.0
"""

View File

@ -66,18 +66,24 @@ def hash_secret(
An encoded hash can be directly passed into :func:`verify_secret` as it
contains all parameters and the salt.
:param bytes secret: Secret to hash.
:param bytes salt: A salt_. Should be random and different for each
secret.
:param Type type: Which Argon2 variant to use.
:param int version: Which Argon2 version to use.
Parameters:
secret: Secret to hash.
salt:
A salt_. Should be random and different for each secret.
type: Which Argon2 variant to use.
version: Which Argon2 version to use.
For an explanation of the Argon2 parameters see
:class:`argon2.PasswordHasher`.
:rtype: bytes
Returns:
An encoded Argon2 hash.
:raises argon2.exceptions.HashingError: If hashing fails.
Raises:
argon2.exceptions.HashingError: If hashing fails.
.. versionadded:: 16.0.0
@ -160,20 +166,28 @@ def verify_secret(hash: bytes, secret: bytes, type: Type) -> Literal[True]:
"""
Verify whether *secret* is correct for *hash* of *type*.
:param bytes hash: An encoded Argon2 hash as returned by
Parameters:
hash:
An encoded Argon2 hash as returned by
:func:`hash_secret`.
:param bytes secret: The secret to verify whether it matches the one
in *hash*.
:param Type type: Type for *hash*.
:raises argon2.exceptions.VerifyMismatchError: If verification fails
because *hash* is not valid for *secret* of *type*.
:raises argon2.exceptions.VerificationError: If verification fails for
other reasons.
secret:
The secret to verify whether it matches the one
in *hash*.
:return: ``True`` on success, raise
type: Type for *hash*.
Raises:
argon2.exceptions.VerifyMismatchError:
If verification fails
because *hash* is not valid for *secret* of *type*.
argon2.exceptions.VerificationError:
If verification fails for
other reasons.
Returns:
``True`` on success, raise
:exc:`~argon2.exceptions.VerificationError` otherwise.
:rtype: bool
.. versionadded:: 16.0.0
.. versionchanged:: 16.1.0
@ -210,13 +224,17 @@ def core(context: Any, type: int) -> int:
Use at your own peril; *argon2-cffi* does *not* use this binding
itself.
:param context: A CFFI Argon2 context object (i.e. an ``struct
Argon2_Context`` / ``argon2_context``).
:param int type: Which Argon2 variant to use. You can use the ``value``
field of :class:`Type`'s fields.
Parameters:
context:
A CFFI Argon2 context object (i.e. an ``struct Argon2_Context`` /
``argon2_context``).
:rtype: int
:return: An Argon2 error code. Can be transformed into a string using
type:
Which Argon2 variant to use. You can use the ``value`` field of
:class:`Type`'s fields.
Returns:
An Argon2 error code. Can be transformed into a string using
:func:`error_to_str`.
.. versionadded:: 16.0.0
@ -228,9 +246,11 @@ def error_to_str(error: int) -> str:
"""
Convert an Argon2 error code into a native string.
:param int error: An Argon2 error code as returned by :func:`core`.
Parameters:
error: An Argon2 error code as returned by :func:`core`.
:rtype: str
Returns:
A human-readable string describing the error.
.. versionadded:: 16.0.0
"""