Skip to content

Commit

Permalink
Add Argon2id
Browse files Browse the repository at this point in the history
  • Loading branch information
hynek committed Nov 10, 2016
1 parent 9f11b63 commit 00120a9
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Expand Up @@ -18,6 +18,7 @@ Changes:
- Fix a bunch of warnings with new ``cffi`` versions and Python 3.6.
`#14 <https://github.com/hynek/argon2_cffi/pull/14>`_
`#16 <https://github.com/hynek/argon2_cffi/pull/16>`_
- Add low-level bindings for Argon2id functions.


----
Expand Down
2 changes: 1 addition & 1 deletion docs/api.rst
Expand Up @@ -53,7 +53,7 @@ Low Level
.. automodule:: argon2.low_level

.. autoclass:: Type
:members: D, I
:members: D, I, ID

.. autodata:: ARGON2_VERSION

Expand Down
5 changes: 4 additions & 1 deletion docs/argon2.rst
Expand Up @@ -12,7 +12,7 @@ It is designed to have both a configurable runtime as well as memory consumption

This means that you can decide how long it takes to hash a password and how much memory is required.

Argon2 comes in two variants:
Argon2 comes in three variants:

Argon2d
is faster and uses data-depending memory access, which makes it less suitable for hashing secrets and more suitable for cryptocurrencies and applications with no threats from side-channel timing attacks.
Expand All @@ -21,6 +21,9 @@ Argon2i
uses data-independent memory access, which is preferred for password hashing and password-based key derivation.
Argon2i is slower as it makes more passes over the memory to protect from tradeoff attacks.

Argon2id
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.


Why “just use bcrypt” Is Not the Best Answer (Anymore)
------------------------------------------------------
Expand Down
6 changes: 5 additions & 1 deletion src/argon2/_ffi_build.py
Expand Up @@ -30,7 +30,11 @@
)

ffi.cdef("""\
typedef enum Argon2_type { Argon2_d = ..., Argon2_i = ... } argon2_type;
typedef enum Argon2_type {
Argon2_d = ...,
Argon2_i = ...,
Argon2_id = ...,
} argon2_type;
typedef enum Argon2_version {
ARGON2_VERSION_10 = ...,
ARGON2_VERSION_13 = ...,
Expand Down
9 changes: 9 additions & 0 deletions src/argon2/low_level.py
Expand Up @@ -52,6 +52,15 @@ class Type(Enum):
password hashing and password-based key derivation. Argon2i is slower as
it makes more passes over the memory to protect from tradeoff attacks.
"""
ID = lib.Argon2_id
r"""
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
"""


def hash_secret(secret, salt, time_cost, memory_cost, parallelism, hash_len,
Expand Down
19 changes: 19 additions & 0 deletions tests/test_low_level.py
Expand Up @@ -39,6 +39,16 @@
# c29tZXNhbHQ$cZn5d+rFh+ZfuRhm2iGUGgcrW5YLeM6q7L3vBsdmFA0
# 0.119 seconds
# Verification ok
#
# Type: Argon2id
# Iterations: 2
# Memory: 65536 KiB
# Parallelism: 4
# Hash: 1a9677b0afe81fda7b548895e7a1bfeb8668ffc19a530e37e088a668fab1c02a
# Encoded: $argon2id$v=19$m=65536,t=2,p=4$
# c29tZXNhbHQ$GpZ3sK/oH9p7VIiV56G/64Zo/8GaUw434IimaPqxwCo
# 0.154 seconds
# Verification ok

TEST_HASH_I_OLD = (
b"$argon2i$m=65536,t=2,p=4"
Expand All @@ -53,12 +63,19 @@
b"$argon2d$v=19$m=65536,t=2,p=4$"
b"c29tZXNhbHQ$cZn5d+rFh+ZfuRhm2iGUGgcrW5YLeM6q7L3vBsdmFA0"
)
TEST_HASH_ID = (
b"$argon2id$v=19$m=65536,t=2,p=4$"
b"c29tZXNhbHQ$GpZ3sK/oH9p7VIiV56G/64Zo/8GaUw434IimaPqxwCo"
)
TEST_RAW_I = binascii.unhexlify(
b"20c8adf6a90550b08c03f5628b32f9edc9d32ce6b90e254cf5e330a40bcfc2be"
)
TEST_RAW_D = binascii.unhexlify(
b"7199f977eac587e65fb91866da21941a072b5b960b78ceaaecbdef06c766140d"
)
TEST_RAW_ID = binascii.unhexlify(
b"1a9677b0afe81fda7b548895e7a1bfeb8668ffc19a530e37e088a668fab1c02a"
)

TEST_PASSWORD = b"password"
TEST_SALT_LEN = 16
Expand All @@ -71,10 +88,12 @@
i_and_d_encoded = pytest.mark.parametrize("type,hash", [
(Type.I, TEST_HASH_I,),
(Type.D, TEST_HASH_D,),
(Type.ID, TEST_HASH_ID,),
])
i_and_d_raw = pytest.mark.parametrize("type,hash", [
(Type.I, TEST_RAW_I,),
(Type.D, TEST_RAW_D,),
(Type.ID, TEST_RAW_ID,),
])

both_hash_funcs = pytest.mark.parametrize("func", [
Expand Down

0 comments on commit 00120a9

Please sign in to comment.