如何使用证书和RSA密钥连接到服务器

时间:2019-04-26 13:42:38

标签: python openssl

我是python编程的新手。 我有一个证书和RAS密钥。而且我想编写一个python ssl套接字客户端程序以将消息发送到server.I知道服务器的主机名和端口。 我一直在尝试下面的代码。

请指导我。

到目前为止,我的代码是:

import socket
import ssl

context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain(certfile="D:/mycerti.crt", keyfile="D:/mykey.key") 

soc = socket.socket() 
soc.bind(('xxx.xxx.xxx.xxx', 3335)) # i am giving actual ip address not xx.xx.xx. 

soc.listen(5) 

但是我一直收到以下错误:

Traceback (most recent call last): File "\test.py", line 7, in <module> soc.bind(('xxx.xxx.xxx.xxx', 3335)) OSError: [WinError 10049] The requested address is not valid in its context

我使用openssl套接字的方式存在错误,我已对其进行了纠正。

context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)  # not CLIENT_AUTH
context.load_cert_chain(certfile="D:/mycerti.crt", keyfile="D:/mykey.key")

soc = socket.socket()
conn = context.wrap_socket(soc, server_hostname='your_server_hostname')  # name, not ip address

conn.connect(('xxx.xxx.xxx.xxx', 3335))

现在我没有收到上述错误,但现在我说错了。

Traceback (most recent call last): 
File "C:/Users/Nouman Yosuf/AppData/Local/Programs/Python/Python37-32/Test.py", line 10, in <module> conn.connect(('x.x.x.x', 3335)) 
File "C:\Users\Nouman Yosuf\AppData\Local\Programs\Python\Python37-32\lib\ssl.py", line 1150, in connect self._real_connect(addr, False) 
File "C:\Users\Nouman Yosuf\AppData\Local\Programs\Python\Python37-32\lib\ssl.py", line 1141, in _real_connect self.do_handshake() 
File "C:\Users\Nouman Yosuf\AppData\Local\Programs\Python\Python37-32\lib\ssl.py", line 1117, in do_handshake self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)

我还以CA和个人身份安装了证书。但是我仍然遇到上述错误。我尝试指定证书路径以及也在安装证书之后。但是仍然无法验证证书,说明无法获取本地发行者证书。 我还尝试从头开始创建上下文。

context = ssl.SSLContext()
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True 
context.load_verify_locations("C:/mycerti.crt") 
soc = socket.socket() 
conn = context.wrap_socket(soc, server_hostname='x.x.x.x') 
conn.connect(('x.x.x.x.', 3335)) 

但是我说错了。

 [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: IP address mismatch, certificate is not valid for 'x.x.x.x. (_ssl.c:1056) 

我确定证书有效或该IP。

1 个答案:

答案 0 :(得分:0)

您很亲密,但缺少几个概念。

首先,如果您是客户端,则将套接字“连接”到服务器。另一方面,服务器“绑定”到端口以“侦听”传入的连接请求。 (类似地,您需要使用ssl.Purpose.SERVER_AUTH而不是ssl.Purpose.CLIENT_AUTH:如果您是服务器,希望对客户端进行身份验证,则使用后者)

第二,您确实为SSL创建了上下文,但是仍然需要将SSLContext与套接字本身相关联。为此,您使用wrap_socket。有了它,就拥有了上下文,有了套接字,但是他们彼此之间并不了解。打包后,您将使用该连接,而不是原始的soc。

请注意,wrap_socket使用服务器名称,而不是IP地址。这是因为它将检查以确保您服务器的证书与服务器提供的证书匹配(相同的IP可以承载许多命名的服务器)。如果不匹配,则连接将失败。

尝试这样的事情:

import socket
import ssl

context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)  # not CLIENT_AUTH
context.load_cert_chain(certfile="D:/mycerti.crt", keyfile="D:/mykey.key")

soc = socket.socket()
conn = context.wrap_socket(soc, server_hostname='your_server_hostname')  # name, not ip address

conn.connect(('xxx.xxx.xxx.xxx', 3335))

# Connection made, so do something, like get the server's certificate
# and see when it expires...
ssl_info = conn.getpeercert()
print sl_info['notAfter']