From a77994408da328e6b0fba331211be9ad2db5c5b6 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 17 Jan 2019 15:56:23 -0600 Subject: support byteslike in ConcatKDF{HMAC,Hash}, Scrypt, and X963KDF (#4709) * byteslike concatkdf * byteslike scrypt * byteslike x963kdf --- .../hazmat/primitives/key-derivation-functions.rst | 9 ++++-- .../hazmat/backends/openssl/backend.py | 3 +- .../hazmat/primitives/kdf/concatkdf.py | 2 +- src/cryptography/hazmat/primitives/kdf/scrypt.py | 2 +- src/cryptography/hazmat/primitives/kdf/x963kdf.py | 2 +- tests/hazmat/primitives/test_concatkdf.py | 35 ++++++++++++++++++++++ tests/hazmat/primitives/test_scrypt.py | 13 ++++++++ tests/hazmat/primitives/test_x963kdf.py | 11 +++++++ 8 files changed, 70 insertions(+), 7 deletions(-) diff --git a/docs/hazmat/primitives/key-derivation-functions.rst b/docs/hazmat/primitives/key-derivation-functions.rst index 373fdbff..64a22c0e 100644 --- a/docs/hazmat/primitives/key-derivation-functions.rst +++ b/docs/hazmat/primitives/key-derivation-functions.rst @@ -377,7 +377,8 @@ Different KDFs are suitable for different tasks such as: .. method:: derive(key_material) - :param bytes key_material: The input key material. + :param key_material: The input key material. + :type key_material: :term:`bytes-like` :return bytes: The derived key. :raises TypeError: This exception is raised if ``key_material`` is not ``bytes``. @@ -562,7 +563,8 @@ Different KDFs are suitable for different tasks such as: .. method:: derive(key_material) - :param bytes key_material: The input key material. + :param key_material: The input key material. + :type key_material: :term:`bytes-like` :return bytes: The derived key. :raises TypeError: This exception is raised if ``key_material`` is not ``bytes``. @@ -813,7 +815,8 @@ Different KDFs are suitable for different tasks such as: .. method:: derive(key_material) - :param bytes key_material: The input key material. + :param key_material: The input key material. + :type key_material: :term:`bytes-like` :return bytes: the derived key. :raises TypeError: This exception is raised if ``key_material`` is not ``bytes``. diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index f74c955a..ab0daa28 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -2181,8 +2181,9 @@ class Backend(object): def derive_scrypt(self, key_material, salt, length, n, r, p): buf = self._ffi.new("unsigned char[]", length) + key_material_ptr = self._ffi.from_buffer(key_material) res = self._lib.EVP_PBE_scrypt( - key_material, len(key_material), salt, len(salt), n, r, p, + key_material_ptr, len(key_material), salt, len(salt), n, r, p, scrypt._MEM_LIMIT, buf, length ) if res != 1: diff --git a/src/cryptography/hazmat/primitives/kdf/concatkdf.py b/src/cryptography/hazmat/primitives/kdf/concatkdf.py index 89c3b282..65b25cdc 100644 --- a/src/cryptography/hazmat/primitives/kdf/concatkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/concatkdf.py @@ -32,7 +32,7 @@ def _common_args_checks(algorithm, length, otherinfo): def _concatkdf_derive(key_material, length, auxfn, otherinfo): - utils._check_bytes("key_material", key_material) + utils._check_byteslike("key_material", key_material) output = [b""] outlen = 0 counter = 1 diff --git a/src/cryptography/hazmat/primitives/kdf/scrypt.py b/src/cryptography/hazmat/primitives/kdf/scrypt.py index 44e369fb..df9745e6 100644 --- a/src/cryptography/hazmat/primitives/kdf/scrypt.py +++ b/src/cryptography/hazmat/primitives/kdf/scrypt.py @@ -52,7 +52,7 @@ class Scrypt(object): raise AlreadyFinalized("Scrypt instances can only be used once.") self._used = True - utils._check_bytes("key_material", key_material) + utils._check_byteslike("key_material", key_material) return self._backend.derive_scrypt( key_material, self._salt, self._length, self._n, self._r, self._p ) diff --git a/src/cryptography/hazmat/primitives/kdf/x963kdf.py b/src/cryptography/hazmat/primitives/kdf/x963kdf.py index a8c07751..fd9d125e 100644 --- a/src/cryptography/hazmat/primitives/kdf/x963kdf.py +++ b/src/cryptography/hazmat/primitives/kdf/x963kdf.py @@ -46,7 +46,7 @@ class X963KDF(object): if self._used: raise AlreadyFinalized self._used = True - utils._check_bytes("key_material", key_material) + utils._check_byteslike("key_material", key_material) output = [b""] outlen = 0 counter = 1 diff --git a/tests/hazmat/primitives/test_concatkdf.py b/tests/hazmat/primitives/test_concatkdf.py index aa568c1f..67315099 100644 --- a/tests/hazmat/primitives/test_concatkdf.py +++ b/tests/hazmat/primitives/test_concatkdf.py @@ -52,6 +52,22 @@ class TestConcatKDFHash(object): assert ckdf.derive(prk) == okm + def test_buffer_protocol(self, backend): + prk = binascii.unhexlify( + b"52169af5c485dcc2321eb8d26d5efa21fb9b93c98e38412ee2484cf14f0d0d23" + ) + + okm = binascii.unhexlify(b"1c3bc9e7c4547c5191c0d478cccaed55") + + oinfo = binascii.unhexlify( + b"a1b2c3d4e53728157e634612c12d6d5223e204aeea4341565369647bd184bcd2" + b"46f72971f292badaa2fe4124612cba" + ) + + ckdf = ConcatKDFHash(hashes.SHA256(), 16, oinfo, backend) + + assert ckdf.derive(bytearray(prk)) == okm + def test_verify(self, backend): prk = binascii.unhexlify( b"52169af5c485dcc2321eb8d26d5efa21fb9b93c98e38412ee2484cf14f0d0d23" @@ -158,6 +174,25 @@ class TestConcatKDFHMAC(object): assert ckdf.derive(prk) == okm + def test_buffer_protocol(self, backend): + prk = binascii.unhexlify( + b"013951627c1dea63ea2d7702dd24e963eef5faac6b4af7e4" + b"b831cde499dff1ce45f6179f741c728aa733583b02409208" + b"8f0af7fce1d045edbc5790931e8d5ca79c73" + ) + + okm = binascii.unhexlify(b"64ce901db10d558661f10b6836a122a7" + b"605323ce2f39bf27eaaac8b34cf89f2f") + + oinfo = binascii.unhexlify( + b"a1b2c3d4e55e600be5f367e0e8a465f4bf2704db00c9325c" + b"9fbd216d12b49160b2ae5157650f43415653696421e68e" + ) + + ckdf = ConcatKDFHMAC(hashes.SHA512(), 32, None, oinfo, backend) + + assert ckdf.derive(bytearray(prk)) == okm + def test_derive_explicit_salt(self, backend): prk = binascii.unhexlify( b"013951627c1dea63ea2d7702dd24e963eef5faac6b4af7e4" diff --git a/tests/hazmat/primitives/test_scrypt.py b/tests/hazmat/primitives/test_scrypt.py index 25d2c615..8f3a14ed 100644 --- a/tests/hazmat/primitives/test_scrypt.py +++ b/tests/hazmat/primitives/test_scrypt.py @@ -108,6 +108,19 @@ class TestScrypt(object): with pytest.raises(TypeError): scrypt.derive(password) + def test_buffer_protocol(self, backend): + password = bytearray(b"password") + work_factor = 256 + block_size = 8 + parallelization_factor = 16 + length = 10 + salt = b"NaCl" + + scrypt = Scrypt(salt, length, work_factor, block_size, + parallelization_factor, backend) + + assert scrypt.derive(password) == b'\xf4\x92\x86\xb2\x06\x0c\x848W\x87' + @pytest.mark.parametrize("params", vectors) def test_verify(self, backend, params): _skip_if_memory_limited(_MEM_LIMIT, params) diff --git a/tests/hazmat/primitives/test_x963kdf.py b/tests/hazmat/primitives/test_x963kdf.py index d87a46b8..c4dd8925 100644 --- a/tests/hazmat/primitives/test_x963kdf.py +++ b/tests/hazmat/primitives/test_x963kdf.py @@ -45,6 +45,17 @@ class TestX963KDF(object): assert xkdf.derive(key) == derivedkey + def test_buffer_protocol(self, backend): + key = bytearray(binascii.unhexlify( + b"96c05619d56c328ab95fe84b18264b08725b85e33fd34f08" + )) + + derivedkey = binascii.unhexlify(b"443024c3dae66b95e6f5670601558f71") + + xkdf = X963KDF(hashes.SHA256(), 16, None, backend) + + assert xkdf.derive(key) == derivedkey + def test_verify(self, backend): key = binascii.unhexlify( b"22518b10e70f2a3f243810ae3254139efbee04aa57c7af7d" -- cgit v1.2.3