Skip to content

Commit

Permalink
Drop md5 and sha1 fingerprints (#2535)
Browse files Browse the repository at this point in the history
* Fix #2267: Drop md5 and sha1 fingerprints

* Add missing changenote

* Fix spelling
  • Loading branch information
asvetlov authored Nov 19, 2017
1 parent e27a20b commit 8e7985a
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 42 deletions.
1 change: 1 addition & 0 deletions CHANGES/2267.removal
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Drop `md5` and `sha1` finger-prints
7 changes: 2 additions & 5 deletions aiohttp/client_reqrep.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,11 +350,8 @@ def update_fingerprint(self, fingerprint):
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)
client_logger.warn('md5 and sha1 are insecure and deprecated. '
'Use sha256.')
raise ValueError('md5 and sha1 are insecure and '
'not supported. Use sha256.')
self._hashfunc = hashfunc
self._fingerprint = fingerprint

Expand Down
10 changes: 3 additions & 7 deletions aiohttp/connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
from .client_reqrep import ClientRequest
from .helpers import is_ip_address, noop, sentinel
from .locks import EventResultOrError
from .log import client_logger
from .resolver import DefaultResolver


Expand Down Expand Up @@ -579,7 +578,7 @@ class TCPConnector(BaseConnector):
"""TCP connector.
verify_ssl - Set to True to check ssl certifications.
fingerprint - Pass the binary md5, sha1, or sha256
fingerprint - Pass the binary sha256
digest of the expected certificate in DER format to verify
that the certificate the server presents matches. See also
https://en.wikipedia.org/wiki/Transport_Layer_Security#Certificate_pinning
Expand Down Expand Up @@ -625,11 +624,8 @@ 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.',
DeprecationWarning, stacklevel=2)
client_logger.warn('md5 and sha1 are insecure and deprecated. '
'Use sha256.')
raise ValueError('md5 and sha1 are insecure and '
'not supported. Use sha256.')
self._hashfunc = hashfunc
self._fingerprint = fingerprint

Expand Down
35 changes: 12 additions & 23 deletions tests/test_client_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,27 +288,18 @@ async def handler(request):
assert txt == 'Test message'


@pytest.mark.parametrize('fingerprint', [
b'\xa2\x06G\xad\xaa\xf5\xd8\\J\x99^by;\x06=',
b's\x93\xfd:\xed\x08\x1do\xa9\xaeq9\x1a\xe3\xc5\x7f\x89\xe7l\xf9',
b'0\x9a\xc9D\x83\xdc\x91\'\x88\x91\x11\xa1d\x97\xfd\xcb~7U\x14D@L'
b'\x11\xab\x99\xa8\xae\xb7\x14\xee\x8b'],
ids=['md5', 'sha1', 'sha256'])
async def test_tcp_connector_fingerprint_ok(test_server, test_client,
loop, ssl_ctx, fingerprint):
loop, ssl_ctx):

fingerprint = (b'0\x9a\xc9D\x83\xdc\x91\'\x88\x91\x11\xa1d\x97\xfd'
b'\xcb~7U\x14D@L'
b'\x11\xab\x99\xa8\xae\xb7\x14\xee\x8b')

async def handler(request):
return web.HTTPOk(text='Test message')

# 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)
connector = aiohttp.TCPConnector(loop=loop, verify_ssl=False,
fingerprint=fingerprint)
app = web.Application()
app.router.add_route('GET', '/', handler)
server = await test_server(app, ssl=ssl_ctx)
Expand All @@ -319,14 +310,12 @@ async def handler(request):
resp.close()


@pytest.mark.parametrize('fingerprint', [
b'\xa2\x06G\xad\xaa\xf5\xd8\\J\x99^by;\x06=',
b's\x93\xfd:\xed\x08\x1do\xa9\xaeq9\x1a\xe3\xc5\x7f\x89\xe7l\xf9',
b'0\x9a\xc9D\x83\xdc\x91\'\x88\x91\x11\xa1d\x97\xfd\xcb~7U\x14D@L'
b'\x11\xab\x99\xa8\xae\xb7\x14\xee\x8b'],
ids=['md5', 'sha1', 'sha256'])
async def test_tcp_connector_fingerprint_fail(test_server, test_client,
loop, ssl_ctx, fingerprint):
loop, ssl_ctx):

fingerprint = (b'0\x9a\xc9D\x83\xdc\x91\'\x88\x91\x11\xa1d\x97\xfd'
b'\xcb~7U\x14D@L'
b'\x11\xab\x99\xa8\xae\xb7\x14\xee\x8b')

async def handler(request):
return web.HTTPOk(text='Test message')
Expand Down
9 changes: 6 additions & 3 deletions tests/test_client_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -1107,12 +1107,15 @@ def test_bad_fingerprint(loop):
fingerprint=b'invalid', loop=loop)


def test_insecure_fingerprint(loop):
with pytest.warns(DeprecationWarning):
def test_insecure_fingerprint_md5(loop):
with pytest.raises(ValueError):
ClientRequest('get', URL('http://python.org'),
fingerprint=hashlib.md5(b"foo").digest(),
loop=loop)
with pytest.warns(DeprecationWarning):


def test_insecure_fingerprint_sha1(loop):
with pytest.raises(ValueError):
ClientRequest('get', URL('http://python.org'),
fingerprint=hashlib.sha1(b"foo").digest(),
loop=loop)
18 changes: 14 additions & 4 deletions tests/test_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -1077,13 +1077,23 @@ def test_tcp_connector_ctor(loop):


def test_tcp_connector_ctor_fingerprint_valid(loop):
valid = b'\xa2\x06G\xad\xaa\xf5\xd8\\J\x99^by;\x06='
# md5 and sha1 are deprecated
with pytest.warns(DeprecationWarning):
conn = aiohttp.TCPConnector(loop=loop, fingerprint=valid)
valid = hashlib.sha256(b"foo").digest()
conn = aiohttp.TCPConnector(fingerprint=valid, loop=loop)
assert conn.fingerprint == valid


def test_insecure_fingerprint_md5(loop):
with pytest.raises(ValueError):
aiohttp.TCPConnector(fingerprint=hashlib.md5(b"foo").digest(),
loop=loop)


def test_insecure_fingerprint_sha1(loop):
with pytest.raises(ValueError):
aiohttp.TCPConnector(fingerprint=hashlib.sha1(b"foo").digest(),
loop=loop)


def test_tcp_connector_fingerprint_invalid(loop):
invalid = b'\x00'
with pytest.raises(ValueError):
Expand Down

0 comments on commit 8e7985a

Please sign in to comment.