From dd427189daf321e1a519b98f1bb167da7ec87673 Mon Sep 17 00:00:00 2001 From: Lukas Puehringer Date: Thu, 13 Oct 2022 15:23:23 +0200 Subject: [PATCH 1/2] Revert to digest sized salts in rsassa-pss signing In #422 we changed `create_rsa_signature` to use the maximum salt length available, instead of the digest length, when creating rsassa-pss signatures, and adapted `verify_rsa_signature` to infer the salt length automatically. This made it impossible for users of the old verify function, which could only handle digest sized salts, to verify signatures created by users of the new signing function (see #430). Since the advantage of max salt lengths is mostly academic, this patch reverts `create_rsa_signature` to use digest sized salts (as agreed in #431). Note that we now use the `padding.PSS.DIGEST_LENGTH` constant instead of passing the actual digest length, as we did before. Using the constant has the same result, but is recommended by the library documentation. Also note that the patch does not revert the `verify_rsa_signature` part of #422. This allows verifying signatures created with the securesystemslib release that used max salt lengths, or created outside of securesystemslib. Signed-off-by: Lukas Puehringer --- securesystemslib/rsa_keys.py | 5 ++--- tests/test_rsa_keys.py | 27 ++++++++++++++++----------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/securesystemslib/rsa_keys.py b/securesystemslib/rsa_keys.py index c260721f..fcf10077 100755 --- a/securesystemslib/rsa_keys.py +++ b/securesystemslib/rsa_keys.py @@ -326,11 +326,10 @@ def create_rsa_signature(private_key, data, scheme='rsassa-pss-sha256'): if scheme.startswith('rsassa-pss'): # Generate an RSSA-PSS signature. Raise # 'securesystemslib.exceptions.CryptoError' for any of the expected - # exceptions raised by pyca/cryptography. 'salt_length' is set to - # the maximum length available. + # exceptions raised by pyca/cryptography. signature = private_key_object.sign( data, padding.PSS(mgf=padding.MGF1(digest_obj.algorithm), - salt_length=padding.PSS.MAX_LENGTH), digest_obj.algorithm) + salt_length=padding.PSS.DIGEST_LENGTH), digest_obj.algorithm) elif scheme.startswith('rsa-pkcs1v15'): # Generate an RSA-PKCS1v15 signature. Raise diff --git a/tests/test_rsa_keys.py b/tests/test_rsa_keys.py index 02b146fd..eff94363 100755 --- a/tests/test_rsa_keys.py +++ b/tests/test_rsa_keys.py @@ -27,6 +27,7 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import padding +from cryptography.hazmat.primitives.hashes import SHA256 from cryptography.hazmat.primitives.serialization import load_pem_private_key public_rsa, private_rsa = securesystemslib.rsa_keys.generate_rsa_public_and_private() @@ -157,26 +158,30 @@ def test_verify_rsa_signature(self): scheme, public_rsa, data)) - def test_verify_rsa_pss_sha256(self): + def test_verify_rsa_pss_different_salt_lengths(self): rsa_scheme = 'rsassa-pss-sha256' - data = 'The ancients say the longer the salt, the more provable the security'.encode('utf-8') + data = 'The ancients say, salt length does not matter that much'.encode('utf-8') private_key = load_pem_private_key(private_rsa.encode('utf-8'), password=None, backend=default_backend()) digest = securesystemslib.hash.digest_from_rsa_scheme(rsa_scheme, 'pyca_crypto') - # Old-style signature: use the hash length as the salt length. - old_signature = private_key.sign(data, - padding.PSS(mgf=padding.MGF1(digest.algorithm), salt_length=padding.PSS.DIGEST_LENGTH), - digest.algorithm) + # Make sure digest size and max salt length are not accidentally the same + self.assertNotEqual(digest.algorithm.digest_size, + padding.calculate_max_pss_salt_length(private_key, digest.algorithm)) - # New-style signature: use the automatic salt length. - new_signature, _ = securesystemslib.rsa_keys.create_rsa_signature(private_rsa, data) + # Sign with max salt length (briefly available in sslib v0.24.0): + max_salt_sig = private_key.sign(data, + padding.PSS(mgf=padding.MGF1(digest.algorithm), salt_length=padding.PSS.MAX_LENGTH), + digest.algorithm) - # Verify both old-style and new-style signatures. - for signature in (old_signature, new_signature): + # Sign with salt length == digest length + fix_salt_sig, _ = securesystemslib.rsa_keys.create_rsa_signature(private_rsa, data) + + # Verification infers salt length automatically and so works for both + for signature in (max_salt_sig, fix_salt_sig): verified = securesystemslib.rsa_keys.verify_rsa_signature(signature, rsa_scheme, - public_rsa, data) + public_rsa, data) self.assertTrue(verified) From de3d1e5a4dd18aeb9485375f1411ea692955d39d Mon Sep 17 00:00:00 2001 From: Lukas Puehringer Date: Thu, 13 Oct 2022 17:03:23 +0200 Subject: [PATCH 2/2] Remove unused import Signed-off-by: Lukas Puehringer --- tests/test_rsa_keys.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_rsa_keys.py b/tests/test_rsa_keys.py index eff94363..92f7c9d9 100755 --- a/tests/test_rsa_keys.py +++ b/tests/test_rsa_keys.py @@ -27,7 +27,6 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import padding -from cryptography.hazmat.primitives.hashes import SHA256 from cryptography.hazmat.primitives.serialization import load_pem_private_key public_rsa, private_rsa = securesystemslib.rsa_keys.generate_rsa_public_and_private()