aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorDavid Reid <dreid@dreid.org>2014-01-29 15:09:49 -0800
committerDavid Reid <dreid@dreid.org>2014-01-29 15:09:49 -0800
commitb2ff87737ca27a171ce0034e100841782d19dd7b (patch)
treefde20b858f07d70a1dcc3f8f2b78bc02480630e5 /tests
parentbabc4d50f42edc1e16c414e4008114d882b4c999 (diff)
parent0b181182aef574c436a92a175937af32e54a2378 (diff)
downloadcryptography-b2ff87737ca27a171ce0034e100841782d19dd7b.tar.gz
cryptography-b2ff87737ca27a171ce0034e100841782d19dd7b.tar.bz2
cryptography-b2ff87737ca27a171ce0034e100841782d19dd7b.zip
Merge pull request #520 from reaperhulk/pbkdf2-openssl
PBKDF2 Support (OpenSSL backend)
Diffstat (limited to 'tests')
-rw-r--r--tests/conftest.py3
-rw-r--r--tests/hazmat/primitives/test_pbkdf2hmac.py69
-rw-r--r--tests/hazmat/primitives/test_pbkdf2hmac_vectors.py37
-rw-r--r--tests/hazmat/primitives/utils.py25
-rw-r--r--tests/test_utils.py19
-rw-r--r--tests/utils.py4
6 files changed, 156 insertions, 1 deletions
diff --git a/tests/conftest.py b/tests/conftest.py
index a9acb54a..ecad1b23 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -2,7 +2,7 @@ import pytest
from cryptography.hazmat.backends import _ALL_BACKENDS
from cryptography.hazmat.backends.interfaces import (
- HMACBackend, CipherBackend, HashBackend
+ HMACBackend, CipherBackend, HashBackend, PBKDF2HMACBackend
)
from .utils import check_for_iface, check_backend_support, select_backends
@@ -21,6 +21,7 @@ def pytest_runtest_setup(item):
check_for_iface("hmac", HMACBackend, item)
check_for_iface("cipher", CipherBackend, item)
check_for_iface("hash", HashBackend, item)
+ check_for_iface("pbkdf2hmac", PBKDF2HMACBackend, item)
check_backend_support(item)
diff --git a/tests/hazmat/primitives/test_pbkdf2hmac.py b/tests/hazmat/primitives/test_pbkdf2hmac.py
new file mode 100644
index 00000000..6ad225a8
--- /dev/null
+++ b/tests/hazmat/primitives/test_pbkdf2hmac.py
@@ -0,0 +1,69 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import absolute_import, division, print_function
+
+import pytest
+import six
+
+from cryptography import utils
+from cryptography.exceptions import (
+ InvalidKey, UnsupportedAlgorithm, AlreadyFinalized
+)
+from cryptography.hazmat.primitives import hashes, interfaces
+from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
+from cryptography.hazmat.backends import default_backend
+
+
+@utils.register_interface(interfaces.HashAlgorithm)
+class DummyHash(object):
+ name = "dummy-hash"
+
+
+class TestPBKDF2HMAC(object):
+ def test_already_finalized(self):
+ kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, default_backend())
+ kdf.derive(b"password")
+ with pytest.raises(AlreadyFinalized):
+ kdf.derive(b"password2")
+
+ kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, default_backend())
+ key = kdf.derive(b"password")
+ with pytest.raises(AlreadyFinalized):
+ kdf.verify(b"password", key)
+
+ kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, default_backend())
+ kdf.verify(b"password", key)
+ with pytest.raises(AlreadyFinalized):
+ kdf.verify(b"password", key)
+
+ def test_unsupported_algorithm(self):
+ with pytest.raises(UnsupportedAlgorithm):
+ PBKDF2HMAC(DummyHash(), 20, b"salt", 10, default_backend())
+
+ def test_invalid_key(self):
+ kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, default_backend())
+ key = kdf.derive(b"password")
+
+ kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, default_backend())
+ with pytest.raises(InvalidKey):
+ kdf.verify(b"password2", key)
+
+ def test_unicode_error_with_salt(self):
+ with pytest.raises(TypeError):
+ PBKDF2HMAC(hashes.SHA1(), 20, six.u("salt"), 10, default_backend())
+
+ def test_unicode_error_with_key_material(self):
+ kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, default_backend())
+ with pytest.raises(TypeError):
+ kdf.derive(six.u("unicode here"))
diff --git a/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py b/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py
new file mode 100644
index 00000000..cbd4cc9d
--- /dev/null
+++ b/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py
@@ -0,0 +1,37 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import absolute_import, division, print_function
+
+import pytest
+
+from cryptography.hazmat.primitives import hashes
+
+from .utils import generate_pbkdf2_test
+from ...utils import load_nist_vectors
+
+
+@pytest.mark.supported(
+ only_if=lambda backend: backend.pbkdf2_hmac_supported(hashes.SHA1()),
+ skip_message="Does not support SHA1 for PBKDF2HMAC",
+)
+@pytest.mark.pbkdf2hmac
+class TestPBKDF2HMAC_SHA1(object):
+ test_pbkdf2_sha1 = generate_pbkdf2_test(
+ load_nist_vectors,
+ "KDF",
+ [
+ "rfc-6070-PBKDF2-SHA1.txt",
+ ],
+ hashes.SHA1(),
+ )
diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py
index f27afe41..6b1d055d 100644
--- a/tests/hazmat/primitives/utils.py
+++ b/tests/hazmat/primitives/utils.py
@@ -4,6 +4,7 @@ import os
import pytest
from cryptography.hazmat.primitives import hashes, hmac
+from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives.ciphers import Cipher
from cryptography.exceptions import (
AlreadyFinalized, NotYetFinalized, AlreadyUpdated, InvalidTag,
@@ -211,6 +212,30 @@ def hmac_test(backend, algorithm, params):
assert h.finalize() == binascii.unhexlify(md.encode("ascii"))
+def generate_pbkdf2_test(param_loader, path, file_names, algorithm):
+ all_params = _load_all_params(path, file_names, param_loader)
+
+ @pytest.mark.parametrize("params", all_params)
+ def test_pbkdf2(self, backend, params):
+ pbkdf2_test(backend, algorithm, params)
+ return test_pbkdf2
+
+
+def pbkdf2_test(backend, algorithm, params):
+ # Password and salt can contain \0, which should be loaded as a null char.
+ # The NIST loader loads them as literal strings so we replace with the
+ # proper value.
+ kdf = PBKDF2HMAC(
+ algorithm,
+ int(params["length"]),
+ params["salt"],
+ int(params["iterations"]),
+ backend
+ )
+ derived_key = kdf.derive(params["password"])
+ assert binascii.hexlify(derived_key) == params["derived_key"]
+
+
def generate_aead_exception_test(cipher_factory, mode_factory):
def test_aead_exception(self, backend):
aead_exception_test(backend, cipher_factory, mode_factory)
diff --git a/tests/test_utils.py b/tests/test_utils.py
index f852f3ab..8ecb33f9 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -180,6 +180,25 @@ def test_load_nist_vectors():
]
+def test_load_nist_vectors_with_null_chars():
+ vector_data = textwrap.dedent("""
+ COUNT = 0
+ KEY = thing\\0withnulls
+
+ COUNT = 1
+ KEY = 00000000000000000000000000000000
+ """).splitlines()
+
+ assert load_nist_vectors(vector_data) == [
+ {
+ "key": b"thing\x00withnulls",
+ },
+ {
+ "key": b"00000000000000000000000000000000",
+ },
+ ]
+
+
def test_load_cryptrec_vectors():
vector_data = textwrap.dedent("""
# Vectors taken from http://info.isl.ntt.co.jp/crypt/eng/camellia/
diff --git a/tests/utils.py b/tests/utils.py
index 507bc421..5c0e524f 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -89,6 +89,10 @@ def load_nist_vectors(vector_data):
# Build our data using a simple Key = Value format
name, value = [c.strip() for c in line.split("=")]
+ # Some tests (PBKDF2) contain \0, which should be interpreted as a
+ # null character rather than literal.
+ value = value.replace("\\0", "\0")
+
# COUNT is a special token that indicates a new block of data
if name.upper() == "COUNT":
test_data = {}