python - 如何使用证书和 rsa 密钥连接到服务器
问题描述
我对python编程很陌生。我有一个证书和 RAS 密钥。我想编写一个 python ssl 套接字客户端程序来向服务器发送消息。我知道服务器主机名和端口。我一直在尝试下面的代码。
请指导我。
我到目前为止的代码是:
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。
解决方案
你很接近,但缺少几个概念。
首先,如果您是客户端,则将您的套接字“连接”到服务器。另一方面,服务器“绑定”到一个端口,“监听”传入的连接请求。(同样,您需要使用 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']
推荐阅读
- c# - 使用 datetime 参数进行远程验证
- spring-data-jpa - HAL 浏览器的标题为空
- sdwebimage - 如何在不快速下载的情况下从图像 url 获取图像大小
- qt - 如何在 qt 中解压缩 .tar 和 lz4 文件?
- python - 修改数据框中的值
- javascript - 在 react-bootstrap-table2 的自定义位置显示选择过滤器
- java - 是否有任何可用于日期格式的默认 Hibernate 验证器?
- android - 尝试使用 ViewModel 从后端获取数据但得到 IllegalArgumentException: Missing public, default no-argument constructor
- android - 将图像存储在 Realm 数据库中以反应本机
- javascript - Pass JavaScript object to controller