From db6fab5a02ec54edb6fe47b4f029a118b4dd26cd Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 10 Mar 2014 21:52:13 -0400 Subject: add MGF1 class, docs, tests --- .../hazmat/primitives/asymmetric/padding.py | 21 +++++++++++++++++ docs/hazmat/primitives/asymmetric/padding.rst | 18 +++++++++++++++ tests/hazmat/primitives/test_rsa.py | 27 ++++++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/cryptography/hazmat/primitives/asymmetric/padding.py b/cryptography/hazmat/primitives/asymmetric/padding.py index 6bafe314..df960b0f 100644 --- a/cryptography/hazmat/primitives/asymmetric/padding.py +++ b/cryptography/hazmat/primitives/asymmetric/padding.py @@ -13,6 +13,8 @@ from __future__ import absolute_import, division, print_function +import six + from cryptography import utils from cryptography.hazmat.primitives import interfaces @@ -20,3 +22,22 @@ from cryptography.hazmat.primitives import interfaces @utils.register_interface(interfaces.AsymmetricPadding) class PKCS1v15(object): name = "EMSA-PKCS1-v1_5" + + +class MGF1(object): + MAX_LENGTH = b"MAX_LENGTH" + + def __init__(self, algorithm, salt_length): + if not isinstance(algorithm, interfaces.HashAlgorithm): + raise TypeError("Expected instance of interfaces.HashAlgorithm.") + + self.algorithm = algorithm + + if (not isinstance(salt_length, six.integer_types) and + salt_length != b"MAX_LENGTH"): + raise TypeError("salt_length must be an integer") + + if salt_length != b"MAX_LENGTH" and salt_length < 0: + raise ValueError("salt_length must be zero or greater") + + self.salt_length = salt_length diff --git a/docs/hazmat/primitives/asymmetric/padding.rst b/docs/hazmat/primitives/asymmetric/padding.rst index 7aec3bd3..632f6985 100644 --- a/docs/hazmat/primitives/asymmetric/padding.rst +++ b/docs/hazmat/primitives/asymmetric/padding.rst @@ -17,4 +17,22 @@ Padding PKCS1 v1.5 (also known as simply PKCS1) is a simple padding scheme developed for use with RSA keys. It is defined in :rfc:`3447`. +Mask Generation Functions +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. class:: MGF1(algorithm, salt_length) + + .. versionadded:: 0.3 + + MGF1 (Mask Generation Function 1) is used as the mask generation function + in :class:`PSS` padding. It takes a hash algorithm and a salt length. + + :param algorithm: An instance of a + :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm` + provider. + + :param int salt_length: The length of the salt. It is recommended that this + be set to ``MGF1.MAX_LENGTH``. + + .. _`Padding is critical`: http://rdist.root.org/2009/10/06/why-rsa-encryption-padding-is-critical/ diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 79323265..c4955478 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -558,3 +558,30 @@ class TestRSAVerification(object): public_key = private_key.public_key() with pytest.raises(TypeError): public_key.verifier(b"sig", "notpadding", hashes.SHA1(), backend) + + +class TestMGF1(object): + def test_invalid_hash_algorithm(self): + with pytest.raises(TypeError): + padding.MGF1(b"not_a_hash", 0) + + def test_invalid_salt_length_not_integer(self): + with pytest.raises(TypeError): + padding.MGF1(hashes.SHA1(), b"not_a_length") + + def test_invalid_salt_length_negative_integer(self): + with pytest.raises(ValueError): + padding.MGF1(hashes.SHA1(), -1) + + def test_valid_mgf1_parameters(self): + algorithm = hashes.SHA1() + salt_length = algorithm.digest_size + mgf = padding.MGF1(algorithm, salt_length) + assert mgf.algorithm == algorithm + assert mgf.salt_length == salt_length + + def test_valid_mgf1_parameters_maximum(self): + algorithm = hashes.SHA1() + mgf = padding.MGF1(algorithm, padding.MGF1.MAX_LENGTH) + assert mgf.algorithm == algorithm + assert mgf.salt_length == padding.MGF1.MAX_LENGTH -- cgit v1.2.3 From 08712cfb25227472d2586164b941f495d4c3b901 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 11 Mar 2014 08:34:28 -0400 Subject: change MAX_LENGTH to be an object rather than a byte string --- cryptography/hazmat/primitives/asymmetric/padding.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cryptography/hazmat/primitives/asymmetric/padding.py b/cryptography/hazmat/primitives/asymmetric/padding.py index df960b0f..62b32dd2 100644 --- a/cryptography/hazmat/primitives/asymmetric/padding.py +++ b/cryptography/hazmat/primitives/asymmetric/padding.py @@ -13,6 +13,8 @@ from __future__ import absolute_import, division, print_function +import collections + import six from cryptography import utils @@ -25,7 +27,7 @@ class PKCS1v15(object): class MGF1(object): - MAX_LENGTH = b"MAX_LENGTH" + MAX_LENGTH = collections.namedtuple("MAX_LENGTH", [])() def __init__(self, algorithm, salt_length): if not isinstance(algorithm, interfaces.HashAlgorithm): @@ -34,10 +36,10 @@ class MGF1(object): self.algorithm = algorithm if (not isinstance(salt_length, six.integer_types) and - salt_length != b"MAX_LENGTH"): + not salt_length is self.MAX_LENGTH): raise TypeError("salt_length must be an integer") - if salt_length != b"MAX_LENGTH" and salt_length < 0: + if not salt_length is self.MAX_LENGTH and salt_length < 0: raise ValueError("salt_length must be zero or greater") self.salt_length = salt_length -- cgit v1.2.3 From d70ed95d37e3ce5f86ed8018e5051ad3aed9fe3a Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 11 Mar 2014 10:07:07 -0400 Subject: make attributes of MGF1 private since that's our general convention --- cryptography/hazmat/primitives/asymmetric/padding.py | 4 ++-- tests/hazmat/primitives/test_rsa.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cryptography/hazmat/primitives/asymmetric/padding.py b/cryptography/hazmat/primitives/asymmetric/padding.py index 62b32dd2..f1c886bf 100644 --- a/cryptography/hazmat/primitives/asymmetric/padding.py +++ b/cryptography/hazmat/primitives/asymmetric/padding.py @@ -33,7 +33,7 @@ class MGF1(object): if not isinstance(algorithm, interfaces.HashAlgorithm): raise TypeError("Expected instance of interfaces.HashAlgorithm.") - self.algorithm = algorithm + self._algorithm = algorithm if (not isinstance(salt_length, six.integer_types) and not salt_length is self.MAX_LENGTH): @@ -42,4 +42,4 @@ class MGF1(object): if not salt_length is self.MAX_LENGTH and salt_length < 0: raise ValueError("salt_length must be zero or greater") - self.salt_length = salt_length + self._salt_length = salt_length diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index c4955478..114dc415 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -577,11 +577,11 @@ class TestMGF1(object): algorithm = hashes.SHA1() salt_length = algorithm.digest_size mgf = padding.MGF1(algorithm, salt_length) - assert mgf.algorithm == algorithm - assert mgf.salt_length == salt_length + assert mgf._algorithm == algorithm + assert mgf._salt_length == salt_length def test_valid_mgf1_parameters_maximum(self): algorithm = hashes.SHA1() mgf = padding.MGF1(algorithm, padding.MGF1.MAX_LENGTH) - assert mgf.algorithm == algorithm - assert mgf.salt_length == padding.MGF1.MAX_LENGTH + assert mgf._algorithm == algorithm + assert mgf._salt_length == padding.MGF1.MAX_LENGTH -- cgit v1.2.3 From 26e5d3fb3e3bd10e97a473ba41f6e0bfc03d7462 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 11 Mar 2014 21:18:06 -0400 Subject: document MAX_LENGTH --- docs/hazmat/primitives/asymmetric/padding.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/hazmat/primitives/asymmetric/padding.rst b/docs/hazmat/primitives/asymmetric/padding.rst index 632f6985..8a034329 100644 --- a/docs/hazmat/primitives/asymmetric/padding.rst +++ b/docs/hazmat/primitives/asymmetric/padding.rst @@ -34,5 +34,10 @@ Mask Generation Functions :param int salt_length: The length of the salt. It is recommended that this be set to ``MGF1.MAX_LENGTH``. + .. attribute:: MAX_LENGTH + + Pass this attribute to ``salt_length`` to get the maximum salt length + available. + .. _`Padding is critical`: http://rdist.root.org/2009/10/06/why-rsa-encryption-padding-is-critical/ -- cgit v1.2.3 From 1c962429404e233e06cb6775f965498ce8b6a5d9 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 14 Mar 2014 12:43:52 -0400 Subject: make MAX_LENGTH an object() --- cryptography/hazmat/primitives/asymmetric/padding.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cryptography/hazmat/primitives/asymmetric/padding.py b/cryptography/hazmat/primitives/asymmetric/padding.py index f1c886bf..181038fa 100644 --- a/cryptography/hazmat/primitives/asymmetric/padding.py +++ b/cryptography/hazmat/primitives/asymmetric/padding.py @@ -13,8 +13,6 @@ from __future__ import absolute_import, division, print_function -import collections - import six from cryptography import utils @@ -27,7 +25,7 @@ class PKCS1v15(object): class MGF1(object): - MAX_LENGTH = collections.namedtuple("MAX_LENGTH", [])() + MAX_LENGTH = object() def __init__(self, algorithm, salt_length): if not isinstance(algorithm, interfaces.HashAlgorithm): -- cgit v1.2.3 From a0fdedef7328615fad7f174d52d6dc36346c7e2f Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 15 Mar 2014 17:28:06 -0400 Subject: restructure if statements to be less confusing --- cryptography/hazmat/primitives/asymmetric/padding.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cryptography/hazmat/primitives/asymmetric/padding.py b/cryptography/hazmat/primitives/asymmetric/padding.py index 181038fa..46e00b8e 100644 --- a/cryptography/hazmat/primitives/asymmetric/padding.py +++ b/cryptography/hazmat/primitives/asymmetric/padding.py @@ -34,10 +34,10 @@ class MGF1(object): self._algorithm = algorithm if (not isinstance(salt_length, six.integer_types) and - not salt_length is self.MAX_LENGTH): + salt_length is not self.MAX_LENGTH): raise TypeError("salt_length must be an integer") - if not salt_length is self.MAX_LENGTH and salt_length < 0: + if salt_length is not self.MAX_LENGTH and salt_length < 0: raise ValueError("salt_length must be zero or greater") self._salt_length = salt_length -- cgit v1.2.3