Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop md5 and sha1 fingerprints #2535

Merged
merged 3 commits into from
Nov 19, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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