From 75a7c1b4023da1ddf8ed971952fbea82d98ffd1b Mon Sep 17 00:00:00 2001 From: jake-jake-jake Date: Wed, 26 Oct 2016 15:25:14 -0400 Subject: [PATCH 1/7] Add warning.warn on MD5 and SHA1 hashes --- aiohttp/connector.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/aiohttp/connector.py b/aiohttp/connector.py index 783e5a309c1..51c51f76e46 100644 --- a/aiohttp/connector.py +++ b/aiohttp/connector.py @@ -441,6 +441,10 @@ def __init__(self, *, verify_ssl=True, fingerprint=None, hashfunc = HASHFUNC_BY_DIGESTLEN.get(digestlen) if not hashfunc: raise ValueError('fingerprint has invalid length') + elif hashfunc is md5 or hashfunc is sha1: + warnings.warn(('md5 and sha1 are insecure and deprecated.', + 'Use sha256.'), + DeprecationWarning, stacklevel=2) self._hashfunc = hashfunc self._fingerprint = fingerprint From c909a8f81733de20255436bcda1f32fc249afb4b Mon Sep 17 00:00:00 2001 From: jake-jake-jake Date: Wed, 26 Oct 2016 15:29:00 -0400 Subject: [PATCH 2/7] Add SHA256 only suggestion to docs --- docs/client_reference.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/client_reference.rst b/docs/client_reference.rst index a84ecb3a27a..d5810d52bd7 100644 --- a/docs/client_reference.rst +++ b/docs/client_reference.rst @@ -886,10 +886,10 @@ TCPConnector *HTTPS* requests (enabled by default). May be disabled to skip validation for sites with invalid certificates. - :param bytes fingerprint: Pass the binary MD5, SHA1, or SHA256 - digest of the expected certificate in DER format to verify - that the certificate the server presents matches. Useful - for `certificate pinning + :param bytes fingerprint: Pass the SHA256 digest of the expected + certificate in DER format to verify that the certificate the + server presents matches. Note: use of MD5 or SHA1 digests is + insecure and deprecated. Useful for `certificate pinning `_. .. versionadded:: 0.16 From d30ac7affecfd0c09f5a7c0b4b2729ab703c684a Mon Sep 17 00:00:00 2001 From: jake-jake-jake Date: Wed, 26 Oct 2016 16:03:50 -0400 Subject: [PATCH 3/7] PyFlakes fix --- aiohttp/connector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aiohttp/connector.py b/aiohttp/connector.py index 51c51f76e46..6050d0339dc 100644 --- a/aiohttp/connector.py +++ b/aiohttp/connector.py @@ -444,7 +444,7 @@ def __init__(self, *, verify_ssl=True, fingerprint=None, elif hashfunc is md5 or hashfunc is sha1: warnings.warn(('md5 and sha1 are insecure and deprecated.', 'Use sha256.'), - DeprecationWarning, stacklevel=2) + DeprecationWarning, stacklevel=2) self._hashfunc = hashfunc self._fingerprint = fingerprint From 2daad84ae7b7b23626a68e3f29adf55b706c9785 Mon Sep 17 00:00:00 2001 From: jake-jake-jake Date: Wed, 26 Oct 2016 16:04:12 -0400 Subject: [PATCH 4/7] changelog --- CHANGES.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index ae1fb8e34a2..c116a7f9ace 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -66,7 +66,8 @@ CHANGES - -- +- Add deprecation warning for MD5 and SHA1 digests when used for fingerprint + of site certs in TCPConnector. #1186 1.0.5 (2016-10-11) ------------------ From 855224eeabd9d48088dbef8ce5e78ea806981b19 Mon Sep 17 00:00:00 2001 From: jake-jake-jake Date: Wed, 26 Oct 2016 16:04:34 -0400 Subject: [PATCH 5/7] Added name to list --- CONTRIBUTORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 14a4d929690..e384ec09b9d 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -65,6 +65,7 @@ Igor Pavlov Ingmar Steen Jacob Champion Jaesung Lee +Jake Davis Jakub Wilk Jashandeep Sohi Jeroen van der Heijden From 33c43c7aa7bfe23a4a9a694c0fdddffe04c92478 Mon Sep 17 00:00:00 2001 From: jake-jake-jake Date: Thu, 27 Oct 2016 09:53:10 -0400 Subject: [PATCH 6/7] Reorder fingerprint param info --- docs/client_reference.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/client_reference.rst b/docs/client_reference.rst index d5810d52bd7..6f24f0ea987 100644 --- a/docs/client_reference.rst +++ b/docs/client_reference.rst @@ -888,10 +888,11 @@ TCPConnector :param bytes fingerprint: Pass the SHA256 digest of the expected certificate in DER format to verify that the certificate the - server presents matches. Note: use of MD5 or SHA1 digests is - insecure and deprecated. Useful for `certificate pinning + server presents matches. Useful for `certificate pinning `_. + Note: use of MD5 or SHA1 digests is insecure and deprecated. + .. versionadded:: 0.16 :param bool use_dns_cache: use internal cache for DNS lookups, ``True`` From 2fe6b8a17a64a3df317a814ac7ac1364d6ad2ae5 Mon Sep 17 00:00:00 2001 From: jake-jake-jake Date: Thu, 27 Oct 2016 11:14:26 -0400 Subject: [PATCH 7/7] Add tests for deprecation warning --- aiohttp/connector.py | 5 +++-- tests/test_client_functional.py | 11 +++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/aiohttp/connector.py b/aiohttp/connector.py index 6050d0339dc..f24354f2969 100644 --- a/aiohttp/connector.py +++ b/aiohttp/connector.py @@ -442,8 +442,9 @@ def __init__(self, *, verify_ssl=True, fingerprint=None, if not hashfunc: raise ValueError('fingerprint has invalid length') elif hashfunc is md5 or hashfunc is sha1: - warnings.warn(('md5 and sha1 are insecure and deprecated.', - 'Use sha256.'), + warnings.simplefilter('always') + warnings.warn('md5 and sha1 are insecure and deprecated. ' + 'Use sha256.', DeprecationWarning, stacklevel=2) self._hashfunc = hashfunc self._fingerprint = fingerprint diff --git a/tests/test_client_functional.py b/tests/test_client_functional.py index 5061c5b761d..5750c0978cf 100644 --- a/tests/test_client_functional.py +++ b/tests/test_client_functional.py @@ -266,8 +266,15 @@ def test_tcp_connector_fingerprint_ok(test_server, test_client, def handler(request): return web.HTTPOk(text='Test message') - connector = aiohttp.TCPConnector(loop=loop, verify_ssl=False, - fingerprint=fingerprint) + # Test for deprecation warning on md5 and sha1 len digests. + if len(fingerprint) == 16 or len(fingerprint) == 20: + with pytest.warns(DeprecationWarning) as cm: + connector = aiohttp.TCPConnector(loop=loop, verify_ssl=False, + fingerprint=fingerprint) + assert 'Use sha256.' in str(cm[0].message) + else: + connector = aiohttp.TCPConnector(loop=loop, verify_ssl=False, + fingerprint=fingerprint) app = web.Application(loop=loop) app.router.add_route('GET', '/', handler) server = yield from test_server(app, ssl=ssl_ctx)