问题
I'm trying to do a small secure HTTPS client for learning purposes and see how all the mechanics of SSL works on a higher level for now, so i'm trying to convert a simple socket into a ssl via ssl.wrap_socket.
I probably got the whole concept backwards but, here's what i'm doing:
s.connect((host, port))
if port == 443:
f = open('cacerts.txt', 'r')
calist = f.read()
f.close()
ca = ssl.get_server_certificate((host, port), ssl_version=ssl.PROTOCOL_SSLv3|ssl.PROTOCOL_TLSv1)
if not ca in calist:
f = open('cacerts.txt', 'a')
f.write(ca)
f.close()
s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv3|ssl.PROTOCOL_TLSv1, cert_reqs=ssl.CERT_REQUIRED, ca_certs="cacerts.txt")
s.do_handshake()
And when i call do_handshake() i get this:
Traceback (most recent call last):
File "SSL_test.py", line 84, in Requester
s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv3|ssl.PROTOCOL_TLSv1, cert_reqs=ssl.CERT_REQUIRED, ca_certs="cacerts.txt")
File "C:\Python26\lib\ssl.py", line 338, in wrap_socket
suppress_ragged_eofs=suppress_ragged_eofs)
File "C:\Python26\lib\ssl.py", line 120, in __init__
self.do_handshake()
File "C:\Python26\lib\ssl.py", line 279, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [Errno 1] _ssl.c:490: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
I've searched around for a while and tried for find something that would be close to what i do, but everyone points to either PyOpenSSL or Twisted and i'd prefer if i could stay out of those libraries, mainly because later on i'm planing on bringing this into a sharp production environment where i'm only allowed to use the built in libraries of Python2.6.
Any help would be greatful!
回答1:
The problem here is that you can't validate a certificate with itself (that is what you are trying to do) unless it is self-signed, and has a CA bit set. You should add a real CA certificate of the web site to the cacerts.txt
file. Another alternative (something like "connect anyway" in a web browser) is to drop the cert_reqs
to ssl.CERT_NONE
after you get such exception, and understand that there could possibly be a man in the middle. This is not the ssl
module issue, this is how SSL/X.509 work.
回答2:
If you are just learning, you can also use Anonymous Diffie-Hellman, that is a server doesn't have a certificate at all, and your client doesn't care to validate it.
Below is a simple (and insecure) test.
Test server, courtesy of openssl
package:
openssl s_server -nocert -cipher "ALL:aNULL:eNULL"
Test client in Python
:
...
ssl.wrap_socket(..., ciphers="ALL:aNULL:eNULL")
...
--
If you want to play with certificates, openssl
package can generate what you want, but it's a bit tricky to get it right. Good GUI tool is TinyCA
, it's written in perl and uses openssl commands, but offers you a decent framework to create own CAs, sign own certificates, etc.
If you're in a hurry, just install apache, start it up, your distro (linux or wamp) will most likely create a self-signed certificate to get you started. Configure apache to the point where you can connect to https://localhost
with a browser. Then use that server to connect to, I think you will get by if you add server's self-signed CA to your clients CA list/file.
来源:https://stackoverflow.com/questions/7497213/python-client-ssl-lib-certificate-verify-failed