Sjuul Janssen
Sjuul Janssen

Reputation: 1812

aiohttp how do I retrieve peer certificate?

I want to get the certificate hash. But I have no idea how to get the server peer certificate. Either in the request or response. The server I send the request to sets the Connection close header, so the retrieving the original ssl socket in the response doesn't work.

Upvotes: 4

Views: 2016

Answers (3)

auxsvr
auxsvr

Reputation: 296

The following works for me with aiohttp 3.8.3:

async with aiohttp.ClientSession() as session:
    r = await session.get('https://bbc.com')
    cert = r.connection.transport.get_extra_info('peercert')

Upvotes: 0

Sjuul Janssen
Sjuul Janssen

Reputation: 1812

I've come up with this solution/hack

import aiohttp


class WrappedResponseClass(aiohttp.ClientResponse):

    def __init__(self, *args, **kwargs):
        super(WrappedResponseClass, self).__init__(*args, **kwargs)
        self._peer_cert = None

    async def start(self, connection, read_until_eof=False):
        try:
            self._peer_cert = connection.transport._ssl_protocol._extra['ssl_object'].getpeercert(True)
        except Exception:
            pass
        return await super(WrappedResponseClass, self).start(connection, read_until_eof)

    @property
    def peer_cert(self):
        return self._peer_cert



session = aiohttp.ClientSession(otherargs..., response_class=WrappedResponseClass)

Upvotes: 1

Andrew Svetlov
Andrew Svetlov

Reputation: 17376

Currently no way, sorry. You can check a cert hash easy though: https://docs.aiohttp.org/en/stable/client_advanced.html#ssl-control-for-tcp-sockets

The following example uses SHA-256 fingerprint check:

fingerprint = b'...'  # should be 64 bytes length hash (256/8)

r = await session.get('https://example.com',
                      ssl=aiohttp.Fingerprint(fingerprint))

Upvotes: 3

Related Questions