From e5852553334c257679a921e03bb37caac3242a69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw=20Pitucha?= Date: Fri, 6 May 2016 16:24:56 +1000 Subject: [PATCH] Better messages for deprecated algos For known, but deprecated algorithms (md{2,4,5}, sha1), log a better message rather than just the OID of the rejected algorithm. Change-Id: I004cbfe486657a80f482e506e4e1fc9396564391 --- anchor/X509/signature.py | 16 ++++++++++++++++ anchor/validators/standards.py | 6 ++++++ tests/validators/test_standards_validator.py | 6 ++++-- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/anchor/X509/signature.py b/anchor/X509/signature.py index 6c14b4f..ef7dfb6 100644 --- a/anchor/X509/signature.py +++ b/anchor/X509/signature.py @@ -29,7 +29,15 @@ from anchor.X509 import errors LOG = logging.getLogger(__name__) +DEPRECATED_ALGORITHM_NAMES = { + asn1_univ.ObjectIdentifier('1.2.840.113549.1.1.2'): 'MD2 with RSA', + asn1_univ.ObjectIdentifier('1.2.840.113549.1.1.3'): 'MD4 with RSA', + asn1_univ.ObjectIdentifier('1.2.840.113549.1.1.4'): 'MD5 with RSA', + asn1_univ.ObjectIdentifier('1.2.840.113549.1.1.5'): 'SHA1 with RSA', + asn1_univ.ObjectIdentifier('1.2.840.10040.4.3'): 'SHA1 with DSA', +} +# valid algorithms sha224WithRSAEncryption = asn1_univ.ObjectIdentifier('1.2.840.113549.1.1.14') sha256WithRSAEncryption = asn1_univ.ObjectIdentifier('1.2.840.113549.1.1.11') sha384WithRSAEncryption = asn1_univ.ObjectIdentifier('1.2.840.113549.1.1.12') @@ -130,6 +138,14 @@ class SignatureMixin(object): except cio_exceptions.InvalidSignature: return False + def uses_deprecated_algorithm(self): + """Check for deprecated algorithm in signatures. + + Returns the name of the algorithm found, or None if everything's ok. + """ + name = DEPRECATED_ALGORITHM_NAMES.get(self._get_signing_algorithm()) + return name + def _get_bytes_to_sign(self): """Get bytes which are giong to be hashed and signed.""" raise NotImplementedError() diff --git a/anchor/validators/standards.py b/anchor/validators/standards.py index 02db731..bfda380 100644 --- a/anchor/validators/standards.py +++ b/anchor/validators/standards.py @@ -86,6 +86,12 @@ def _valid_domains(csr): def _csr_signature(csr): """Ensure that the CSR has a valid self-signature.""" + # first check for deprecated signatures - verification on those will fail + algo = csr.uses_deprecated_algorithm() + if algo: + raise errors.ValidationError("CSR rejected for using a known broken, " + "or deprecated algorithm: %s" % algo) + try: if not csr.verify(): raise errors.ValidationError("Signature on the CSR is not valid") diff --git a/tests/validators/test_standards_validator.py b/tests/validators/test_standards_validator.py index 04ded1d..060f602 100644 --- a/tests/validators/test_standards_validator.py +++ b/tests/validators/test_standards_validator.py @@ -177,11 +177,13 @@ class TestCsrSignature(tests.DefaultRequestMixin, unittest.TestCase): "Signature on the CSR is not valid"): standards._csr_signature(csr=csr) - def test_csr_signature_bad_algo(self): + def test_csr_signature_old_algo(self): csr = signing_request.X509Csr.from_buffer(self.csr_sample_bytes) with mock.patch.object(signing_request.X509Csr, '_get_signing_algorithm', return_value=rfc2459.id_dsa_with_sha1): with self.assertRaisesRegexp(errors.ValidationError, - "Signature on the CSR is not valid"): + "CSR rejected for using a known " + "broken, or deprecated algorithm: " + "SHA1 with DSA"): standards._csr_signature(csr=csr)