Skip to content

Commit

Permalink
Update argon2, make cffi figure out values
Browse files Browse the repository at this point in the history
Also add an integration test that checks that for most reasonable values, both
hashing and verifying works.
  • Loading branch information
hynek committed Jan 25, 2016
1 parent 0bb9563 commit 675576a
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 46 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ The third digit is only for regressions.
16.1.0 (UNRELEASED)
-------------------

Vendoring ``argon2`` @ ea8545a3ad16b7be2a49288050debdba7b312b9a_.
Vendoring ``argon2`` @ 6411c26acdda38aff9f94785787f64dc7c39cd72_.

Deprecations:
^^^^^^^^^^^^^
Expand Down Expand Up @@ -83,6 +83,6 @@ Previous betas were only for fixing Windows packaging.
The authors of ``argon2`` were kind enough to `help me <https://github.com/P-H-C/phc-winner-argon2/issues/44>`_ to get it building under Visual Studio 2008 that we’re forced to use for Python 2.7 on Windows.


.. _ea8545a3ad16b7be2a49288050debdba7b312b9a: https://github.com/P-H-C/phc-winner-argon2/tree/ea8545a3ad16b7be2a49288050debdba7b312b9a
.. _6411c26acdda38aff9f94785787f64dc7c39cd72: https://github.com/P-H-C/phc-winner-argon2/tree/6411c26acdda38aff9f94785787f64dc7c39cd72
.. _421dafd2a8af5cbb215e16da5953663eb101d139: https://github.com/P-H-C/phc-winner-argon2/tree/421dafd2a8af5cbb215e16da5953663eb101d139
.. _4fe0d8cda37691228dd5a96a310be57369403a4b: https://github.com/P-H-C/phc-winner-argon2/tree/4fe0d8cda37691228dd5a96a310be57369403a4b
2 changes: 1 addition & 1 deletion extras/libargon2
89 changes: 52 additions & 37 deletions src/argon2/_ffi_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
)

ffi.cdef("""\
typedef enum Argon2_type { Argon2_d = 0, Argon2_i = 1 } argon2_type;
typedef enum Argon2_type { Argon2_d = ..., Argon2_i = ... } argon2_type;
int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
Expand All @@ -43,7 +43,7 @@
int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
argon2_type type);
const char *error_message(int error_code);
const char *argon2_error_message(int error_code);
typedef int (*allocate_fptr)(uint8_t **memory, size_t bytes_to_allocate);
Expand Down Expand Up @@ -76,63 +76,66 @@
uint32_t flags; /* array of bool options */
} argon2_context;
int argon2_core(argon2_context *context, argon2_type type);
int argon2_ctx(argon2_context *context, argon2_type type);
/* Error codes */
typedef enum Argon2_ErrorCodes {
ARGON2_OK = 0,
ARGON2_OK = ...,
ARGON2_OUTPUT_PTR_NULL = 1,
ARGON2_OUTPUT_PTR_NULL = ...,
ARGON2_OUTPUT_TOO_SHORT = 2,
ARGON2_OUTPUT_TOO_LONG = 3,
ARGON2_OUTPUT_TOO_SHORT = ...,
ARGON2_OUTPUT_TOO_LONG = ...,
ARGON2_PWD_TOO_SHORT = 4,
ARGON2_PWD_TOO_LONG = 5,
ARGON2_PWD_TOO_SHORT = ...,
ARGON2_PWD_TOO_LONG = ...,
ARGON2_SALT_TOO_SHORT = 6,
ARGON2_SALT_TOO_LONG = 7,
ARGON2_SALT_TOO_SHORT = ...,
ARGON2_SALT_TOO_LONG = ...,
ARGON2_AD_TOO_SHORT = 8,
ARGON2_AD_TOO_LONG = 9,
ARGON2_AD_TOO_SHORT = ...,
ARGON2_AD_TOO_LONG = ...,
ARGON2_SECRET_TOO_SHORT = 10,
ARGON2_SECRET_TOO_LONG = 11,
ARGON2_SECRET_TOO_SHORT = ...,
ARGON2_SECRET_TOO_LONG = ...,
ARGON2_TIME_TOO_SMALL = 12,
ARGON2_TIME_TOO_LARGE = 13,
ARGON2_TIME_TOO_SMALL = ...,
ARGON2_TIME_TOO_LARGE = ...,
ARGON2_MEMORY_TOO_LITTLE = 14,
ARGON2_MEMORY_TOO_MUCH = 15,
ARGON2_MEMORY_TOO_LITTLE = ...,
ARGON2_MEMORY_TOO_MUCH = ...,
ARGON2_LANES_TOO_FEW = 16,
ARGON2_LANES_TOO_MANY = 17,
ARGON2_PWD_PTR_MISMATCH = 18, /* NULL ptr with non-zero length */
ARGON2_SALT_PTR_MISMATCH = 19, /* NULL ptr with non-zero length */
ARGON2_SECRET_PTR_MISMATCH = 20, /* NULL ptr with non-zero length */
ARGON2_AD_PTR_MISMATCH = 21, /* NULL ptr with non-zero length */
ARGON2_LANES_TOO_FEW = ...,
ARGON2_LANES_TOO_MANY = ...,
ARGON2_MEMORY_ALLOCATION_ERROR = 22,
ARGON2_PWD_PTR_MISMATCH = ..., /* NULL ptr with non-zero length */
ARGON2_SALT_PTR_MISMATCH = ..., /* NULL ptr with non-zero length */
ARGON2_SECRET_PTR_MISMATCH = ..., /* NULL ptr with non-zero length */
ARGON2_AD_PTR_MISMATCH = ..., /* NULL ptr with non-zero length */
ARGON2_FREE_MEMORY_CBK_NULL = 23,
ARGON2_ALLOCATE_MEMORY_CBK_NULL = 24,
ARGON2_MEMORY_ALLOCATION_ERROR = ...,
ARGON2_INCORRECT_PARAMETER = 25,
ARGON2_INCORRECT_TYPE = 26,
ARGON2_FREE_MEMORY_CBK_NULL = ...,
ARGON2_ALLOCATE_MEMORY_CBK_NULL = ...,
ARGON2_OUT_PTR_MISMATCH = 27,
ARGON2_INCORRECT_PARAMETER = ...,
ARGON2_INCORRECT_TYPE = ...,
ARGON2_THREADS_TOO_FEW = 28,
ARGON2_THREADS_TOO_MANY = 29,
ARGON2_OUT_PTR_MISMATCH = ...,
ARGON2_MISSING_ARGS = 30,
ARGON2_THREADS_TOO_FEW = ...,
ARGON2_THREADS_TOO_MANY = ...,
ARGON2_ENCODING_FAIL = 31,
ARGON2_MISSING_ARGS = ...,
ARGON2_DECODING_FAIL = 32,
ARGON2_ENCODING_FAIL = ...,
ARGON2_THREAD_FAIL = 33,
ARGON2_DECODING_FAIL = ...,
ARGON2_THREAD_FAIL = ...,
ARGON2_DECODING_LENGTH_FAIL= ...,
ARGON2_ERROR_CODES_LENGTH /* Do NOT remove; Do NOT add error codes after
this
Expand All @@ -143,6 +146,18 @@
#define ARGON2_FLAG_CLEAR_SECRET ...
#define ARGON2_FLAG_CLEAR_MEMORY ...
#define ARGON2_DEFAULT_FLAGS ...
#define ARGON2_MIN_LANES ...
#define ARGON2_MAX_LANES ...
#define ARGON2_MIN_OUTLEN ...
#define ARGON2_MAX_OUTLEN ...
#define ARGON2_MIN_TIME ...
#define ARGON2_MAX_TIME ...
#define ARGON2_MIN_PWD_LENGTH ...
#define ARGON2_MAX_PWD_LENGTH ...
#define ARGON2_MIN_SALT_LENGTH ...
#define ARGON2_MAX_SALT_LENGTH ...
""")

if __name__ == '__main__':
Expand Down
6 changes: 3 additions & 3 deletions src/argon2/low_level.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ def verify_secret(hash, secret, type):

def core(context, type):
"""
Direct binding to the Argon2 ``core`` function.
Direct binding to the ``argon2_ctx`` function.
.. warning::
This is a strictly advanced function working on raw C data structures.
Expand All @@ -161,7 +161,7 @@ def core(context, type):
.. versionadded:: 16.0.0
"""
return lib.argon2_core(context, type)
return lib.argon2_ctx(context, type)


def error_to_str(error):
Expand All @@ -174,7 +174,7 @@ def error_to_str(error):
.. versionadded:: 16.0.0
"""
msg = ffi.string(lib.error_message(error))
msg = ffi.string(lib.argon2_error_message(error))
if PY3:
msg = msg.decode("ascii")
return msg
2 changes: 1 addition & 1 deletion tests/test_legacy.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def test_success(self, type, hash):
"""
assert True is verify_password(hash, TEST_PASSWORD, type)

def test_fail(self):
def test_fail_wrong_argon2_type(self):
"""
Given a valid hash and password and wrong type, we fail.
"""
Expand Down
44 changes: 42 additions & 2 deletions tests/test_low_level.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from __future__ import absolute_import, division, print_function

import binascii
import os

import pytest

from hypothesis import given
from hypothesis import given, assume
from hypothesis import strategies as st

from argon2.low_level import (
Expand Down Expand Up @@ -184,10 +185,20 @@ def test_success(self, type, hash):
"""
assert True is verify_secret(hash, TEST_PASSWORD, type)

def test_fail(self):
@i_and_d_encoded
def test_fail(self, type, hash):
"""
Wrong password fails.
"""
with pytest.raises(VerificationError):
verify_secret(hash, bytes(reversed(TEST_PASSWORD)), type)

def test_fail_wrong_argon2_type(self):
"""
Given a valid hash and secret and wrong type, we fail.
"""
verify_secret(TEST_HASH_D, TEST_PASSWORD, Type.D)
verify_secret(TEST_HASH_I, TEST_PASSWORD, Type.I)
with pytest.raises(VerificationError):
verify_secret(TEST_HASH_I, TEST_PASSWORD, Type.D)

Expand All @@ -199,6 +210,35 @@ def test_wrong_arg_type(self):
verify_secret(TEST_HASH_I, TEST_PASSWORD.decode("ascii"))


@given(
password=st.binary(lib.ARGON2_MIN_PWD_LENGTH, 65),
time_cost=st.integers(lib.ARGON2_MIN_TIME, 3),
parallelism=st.integers(lib.ARGON2_MIN_LANES, 5),
memory_cost=st.integers(0, 1025),
hash_len=st.integers(lib.ARGON2_MIN_OUTLEN, 513),
salt_len=st.integers(lib.ARGON2_MIN_SALT_LENGTH, 513),
)
def test_argument_ranges(password, time_cost, parallelism, memory_cost,
hash_len, salt_len):
"""
Ensure that both hashing and verifying works for most combinations of legal
values.
Limits are intentionally chosen to be *not* on 2^x boundaries.
This test is rather slow.
"""
assume(parallelism * 8 <= memory_cost)
hash = hash_secret(
secret=password, salt=os.urandom(salt_len),
time_cost=time_cost, parallelism=parallelism,
memory_cost=memory_cost,
hash_len=hash_len,
type=Type.I,
)
assert verify_secret(hash, password, Type.I)


def test_core():
"""
If called with equal parameters, core() will return the same as
Expand Down

0 comments on commit 675576a

Please sign in to comment.