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)