Is there a way to get remote peer certificate with

2019-03-04 17:56发布

问题:

I am using Python 3. I am using a SSLContext from the ssl library.

I would like to know how to request and get the remote peer certificate (as with SSLSocket.getpeercert()) but in the CERT_NONE mode. Currently, I get an empty dict (which is expected as per the documentation). So, can I do that without digging into private stuff?

N.B.

I am not trying to reimplement crypto. Actually, I don't need any crypto, however I need the context (and a socket) and the remote certificate (again, for information purpose, not to authenticate or actually encrypt anything).

回答1:

Python/OpenSSL mix requesting the client certificate certificate with validating it:

  • CERT_NONE (OpenSSL: SSL_VERIFY_NONE) will not request the certificate from the client at all. This means the client will not send a certificate.
  • CERT_REQUIRE (OpenSSL: SSL_VERFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT) and CERT_OPTIONAL (OpenSSL: SSL_VERIFY_PEER) will request the certificate but then also fail if the certificate could not be verified.

What you would need is to require the certificate but then have a way to handle the validation yourself and just accept all client certificates. This could be done with a custom verification callback. In OpenSSL this could be done with SSL_CTX_set_verify. But unfortunately the Python ssl library don't seem to expose the necessary interface to have your own validation callback. But it should be possible to do with pyOpenSSL which lets you set your own verification callback.



回答2:

I found a way without straying away from the default ssl library (which has the advantage of being there):

socket.getpeercert(binary_form=True)

gives the certificate in DER format which is good enough for what I have to do.

Afaik, returning an empty dict is to avoid blindly trusting what people send in clear text and has not been verified.