1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
|
API Reference
=============
.. module:: argon2
.. autoclass:: PasswordHasher
:members: from_parameters, hash, verify, check_needs_rehash
If you don't specify any parameters, the following constants are used:
.. data:: DEFAULT_RANDOM_SALT_LENGTH
.. data:: DEFAULT_HASH_LENGTH
.. data:: DEFAULT_TIME_COST
.. data:: DEFAULT_MEMORY_COST
.. data:: DEFAULT_PARALLELISM
They are taken from :data:`argon2.profiles.RFC_9106_LOW_MEMORY`, but they may vary depending on the platform.
You can use :func:`argon2.profiles.get_default_parameters` to get the current platform's defaults.
Profiles
--------
.. automodule:: argon2.profiles
You can try them out using the :doc:`cli` interface.
For example:
.. code-block:: console
$ python -m argon2 --profile RFC_9106_HIGH_MEMORY
Running Argon2id 100 times with:
hash_len: 32 bytes
memory_cost: 2097152 KiB
parallelism: 4 threads
time_cost: 1 iterations
Measuring...
866.5ms per password verification
That should give you a feeling on how they perform in *your* environment.
.. data:: RFC_9106_HIGH_MEMORY
Called "FIRST RECOMMENDED option" by `RFC 9106`_.
Requires beefy 2 GiB, so be careful in memory-contrained systems.
.. versionadded:: 21.2.0
.. data:: RFC_9106_LOW_MEMORY
Called "SECOND RECOMMENDED option" by `RFC 9106`_.
The main difference is that it only takes 64 MiB of RAM.
The values from this profile are the default parameters used by :class:`argon2.PasswordHasher`.
.. versionadded:: 21.2.0
.. data:: PRE_21_2
The default values that *argon2-cffi* used from 18.2.0 until 21.2.0.
Needs 100 MiB of RAM.
.. versionadded:: 21.2.0
.. data:: CHEAPEST
This is the cheapest-possible profile.
.. warning::
This is only for testing purposes!
Do **not** use in production!
.. versionadded:: 21.2.0
.. autofunction:: argon2.profiles.get_default_parameters
.. _`RFC 9106`: https://www.rfc-editor.org/rfc/rfc9106.html
Exceptions
----------
.. autoexception:: argon2.exceptions.VerificationError
.. autoexception:: argon2.exceptions.VerifyMismatchError
.. autoexception:: argon2.exceptions.HashingError
.. autoexception:: argon2.exceptions.InvalidHashError
.. autoexception:: argon2.exceptions.InvalidHash
.. autoexception:: argon2.exceptions.UnsupportedParametersError
Utilities
---------
.. autofunction:: argon2.extract_parameters
.. autoclass:: argon2.Parameters
Low Level
---------
.. automodule:: argon2.low_level
.. autoclass:: Type()
.. attribute:: D
Argon2\ **d** is faster and uses data-depending memory access.
That makes it less suitable for hashing secrets and more suitable for cryptocurrencies and applications with no threats from side-channel timing attacks.
.. attribute:: I
Argon2\ **i** uses data-independent memory access.
Argon2i is slower as it makes more passes over the memory to protect from tradeoff attacks.
.. attribute:: ID
Argon2\ **id** is a hybrid of Argon2i and Argon2d, using a combination of data-depending and data-independent memory accesses, which gives some of Argon2i's resistance to side-channel cache timing attacks and much of Argon2d's resistance to GPU cracking attacks.
.. versionadded:: 16.3.0
.. autodata:: ARGON2_VERSION
.. autofunction:: hash_secret
.. doctest::
>>> import argon2
>>> argon2.low_level.hash_secret(
... b"secret", b"somesalt",
... time_cost=1, memory_cost=8, parallelism=1, hash_len=64, type=argon2.low_level.Type.D
... )
b'$argon2d$v=19$m=8,t=1,p=1$c29tZXNhbHQ$ba2qC75j0+JAunZZ/L0hZdQgCv+tOieBuKKXSrQiWm7nlkRcK+YqWr0i0m0WABJKelU8qHJp0SZzH0b1Z+ITvQ'
.. autofunction:: verify_secret
The raw hash can also be computed:
.. autofunction:: hash_secret_raw
.. doctest::
>>> argon2.low_level.hash_secret_raw(
... b"secret", b"somesalt",
... time_cost=1, memory_cost=8, parallelism=1, hash_len=8, type=argon2.low_level.Type.D
... )
b'\xe4n\xf5\xc8|\xa3>\x1d'
The super low-level ``argon2_core()`` function is exposed too if you need access to very specific options:
.. autofunction:: core
In order to use :func:`core`, you need access to *argon2-cffi*'s FFI objects.
Therefore, it is OK to use ``argon2.low_level.ffi`` and ``argon2.low_level.lib`` when working with it.
For example, if you wanted to check the :rfc:`9106` test vectors for Argon2id that include a secret and associated data that both get mixed into the hash and aren't exposed by the high-level APIs:
.. doctest::
>>> from argon2.low_level import Type, core, ffi, lib
>>> def low_level_hash(
... password, salt, secret, associated,
... hash_len, version, t_cost, m_cost, lanes, threads):
... cout = ffi.new("uint8_t[]", hash_len)
... cpwd = ffi.new("uint8_t[]", password)
... cad = ffi.new("uint8_t[]", associated)
... csalt = ffi.new("uint8_t[]", salt)
... csecret = ffi.new("uint8_t[]", secret)
...
... ctx = ffi.new(
... "argon2_context *",
... {
... "out": cout,
... "outlen": hash_len,
... "version": version,
... "pwd": cpwd,
... "pwdlen": len(cpwd) - 1,
... "salt": csalt,
... "saltlen": len(csalt) - 1,
... "secret": csecret,
... "secretlen": len(csecret) - 1,
... "ad": cad,
... "adlen": len(cad) - 1,
... "t_cost": t_cost,
... "m_cost": m_cost,
... "lanes": lanes,
... "threads": threads,
... "allocate_cbk": ffi.NULL,
... "free_cbk": ffi.NULL,
... "flags": lib.ARGON2_DEFAULT_FLAGS,
... },
... )
...
... assert lib.ARGON2_OK == core(ctx, Type.ID.value)
...
... return bytes(ffi.buffer(ctx.out, ctx.outlen)).hex()
>>> password = bytes.fromhex(
... "0101010101010101010101010101010101010101010101010101010101010101"
... )
>>> associated = bytes.fromhex("040404040404040404040404")
>>> salt = bytes.fromhex("02020202020202020202020202020202")
>>> secret = bytes.fromhex("0303030303030303")
>>> assert (
... "0d640df58d78766c08c037a34a8b53c9d01ef0452d75b65eb52520e96b01e659"
... == low_level_hash(
... password, salt, secret, associated,
... 32, 19, 3, 32, 4, 4,
... )
... )
All constants and types on ``argon2.low_level.lib`` are guaranteed to stay as long they are not altered by Argon2 itself.
.. autofunction:: error_to_str
Deprecated APIs
---------------
These APIs are from the first release of *argon2-cffi* and proved to live in an unfortunate mid-level.
On one hand they have defaults and check parameters but on the other hand they only consume byte strings.
Therefore the decision has been made to replace them by a high-level (:class:`argon2.PasswordHasher`) and a low-level (:mod:`argon2.low_level`) solution.
They will be removed in 2024.
.. autofunction:: argon2.hash_password
.. autofunction:: argon2.hash_password_raw
.. autofunction:: argon2.verify_password
|