gpt4 book ai didi

Python SSL 验证失败

转载 作者:太空宇宙 更新时间:2023-11-03 14:34:49 24 4
gpt4 key购买 nike

我正在尝试设置 Python TCP 客户端-服务器 session ,但客户端抛出此错误:[SSL: CERTIFICATE_VERIFY_FAILED] 证书验证失败 (_ssl.c:777)

我正在使用新生成的 LetsEncrypt 证书。我已经将 fullchain.pem(公共(public)证书)存储在我运行客户端的计算机上,但它无法验证真实性。我确定 fullchain.pem 是公钥,privkey.pem 是私钥,所以我不明白为什么这不起作用。我也尝试过将 cert.pem 用于 public,但这也不起作用。是否有人能够就验证失败的原因提供一些见解?下面是客户端和服务器程序。

客户:

import sys
import socket
import os
import ssl
from backports.ssl_match_hostname import match_hostname, CertificateError


def connect(hostname, port, message):
"""
Connects to the hostname on the specified port and sends a message

:param hostname:
:param port:
:param message:
:return:
"""

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # create a TCP socket
try:
s.connect((hostname, port)) # establish a TCP connection to the host
#ca_certs_path = os.path.join(os.path.dirname(sys.argv[0]), 'fullchain.pem')
ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)
#sslsock = ctx.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv23, cert_reqs=ssl.CERT_REQUIRED, ca_certs=ca_certs_path)
sslsock = ctx.wrap_socket(s, server_hostname='encryptio.tk')

# Check if the server really matches the hostname to which we are trying to connect
match_hostname(sslsock.getpeercert(), hostname)

sslsock.send(message.encode('utf-8')) # send the message
except Exception as e:
sys.exit('[-]' + str(e))


def main():
connect('encryptio.tk', 12000, 'Client says hello') # replace '' with the hostname, 12000 as the port, and 'Hello' as the message


if __name__ == '__main__':
main()

服务器:

import sys
import socket
import ssl
from backports.ssl_match_hostname import match_hostname, CertificateError

# Servers do not care whether clients connect with certificates

def listen(port):
"""
Listens on the specified port and accepts incoming connections

:param port:
:return:
"""

# server_socket - welcoming socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('', port)) # establish welcoming socket

ca_certs_path = '/etc/letsencrypt/live/encryptio.tk/fullchain.pem'
priv_certs_path = '/etc/letsencrypt/live/encryptio.tk/privkey.pem'

# listen for TCP connection requests.
server_socket.listen(1) # parameter specifies the maximum number of queued connections (at least 1)

ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ctx.load_cert_chain(certfile=ca_certs_path, keyfile=priv_certs_path)

server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

print('[*] The server is ready to receive')

while 1:
try:
# When a client knocks on this door, the program invokes the accept() method for
# server_socket, which creates a new socket in the server, called connec-
# tion_ocket, dedicated to this particular client. The client and server then complete
# the handshaking, creating a TCP connection between the client’s client_socket
# and the server’s connection_socket
#connection_socket, addr = server_socket.accept()

#sslsock = ssl.wrap_socket(server_socket, ssl_version=ssl.PROTOCOL_SSLv23, cert_reqs=ssl.CERT_REQUIRED, server_side=True, certfile=ca_certs_path, keyfile=priv_certs_path)
connection_socket, addr = server_socket.accept()
sslsock = ctx.wrap_socket(connection_socket, server_side=True)
data = sslsock.read()
#message = connection_socket.recv(1500)

print('[+] From' + str(addr) + ': ' +
data.decode('utf-8'))
except Exception as e:
sys.exit('[-] ' + str(e))

#connection_socket.close()
sslsock.shutdown(socket.SHUT_RDWR)
sslsock.close()


def main():
listen(12000)


if __name__ == '__main__':
main()

编辑:我尝试将客户端程序中的 CA 设置为根证书,但现在出现此错误:

[X509] PEM lib (_ssl.c:3053)

最佳答案

在你的客户中你有这个:

 ca_certs_path = os.path.join(os.path.dirname(sys.argv[0]), 'fullchain.pem')
sslsock = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv23,
cert_reqs=ssl.CERT_REQUIRED, ca_certs=ca_certs_path)

ca_certs 的默认值在 ssl.wrap_socket 中为 None,这意味着如果您使用非默认的 ssl.CERT_REQUIRED,则必须提供有用的路径。只有,您提供的路径似乎是您在服务器中使用的证书链,即服务器证书和链证书,但不是根证书。相反,客户端的 ca_certs 应该只包含根证书,因为这是用于使用服务器发送的证书(即服务器证书和链)构建信任链的信任 anchor 。

除了使用您自己的 CA 存储之外,您还可以使用系统范围的存储。使用当前版本的 Python,您可以简单地使用以下代码,它使用默认 CA 存储创建 SSL 上下文并启用证书和主机名验证,然后将套接字升级到 SSL 并正确检查证书:

 s.connect((hostname, port))
ctx = ssl.create_default_context()
sslsock = ctx.wrap_socket(s, server_hostname='example.com')

关于Python SSL 验证失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48939942/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com