我正在熟悉Python中的openssl,使用自签名证书的简单套接字服务器/客户端。有一个细节让我感到困惑。我创建了一个CA证书,我用它来自签名证书csr的使用x509为服务器和客户端生成.当使用产生的证书和私钥在服务器和客户端,我注意到,每个对等需要使用其他对等的crt作为cafile在create_缺省上下文例如,客户端在create_default_context中使用服务器的crt作为ca(),然后在load_cert_chain中输入自己的crt和key由于两个对等体的crt都使用相同的ca crt进行签名,我认为它们需要ca crt作为create_default_context的cafile(),而不是其他对等体的crt。但是如果我使用公共ca crt,我反而得到了no shared cipher错误。为什么会这样?
繁衍
- 证书创建 *
1)CA:
openssl genrsa -aes256 -passout pass:changeme -out ca.pass.key 4096
openssl rsa -passin pass:changeme -in ca.pass.key -out ca.key
openssl req -new -x509 -days 365 -key ca.key -out ca.crt
2)客户端和服务器(其中“用户”是客户端或服务器):
openssl genrsa -aes256 -passout pass:changeme -out user.pass.key 4096
openssl rsa -passin pass:changeme -in user.pass.key -out user.key
openssl req -new -key user.key -out user.csr
openssl x509 -CAcreateserial -req -days 365 -in user.csr -CA ca.crt -CAkey ca.key -out user.crt
echo_client.py
import socket, ssl
server = ("127.0.0.1", 1234)
ssl_context = ssl.create_default_context(
ssl.Purpose.SERVER_AUTH,
cafile='ca.crt'
)
ssl_context.load_cert_chain(
certfile='client.crt',
keyfile='client.key'
)
with socket.socket(
socket.AF_INET,
socket.SOCK_STREAM
) as session:
with ssl_context.wrap_socket(session, server_side=False, server_hostname=server[0]) as secure_session:
secure_session.connect(server)
while True:
data = bytes(input("Enter message:\n"), "ASCII")
secure_session.sendall(data)
echo = secure_session.recv(1024)
print(f"Echo: {echo}")
echo_server.py
import socket, ssl, sys
def main(PORT_NUMBER):
ssl_context = ssl.create_default_context(
ssl.Purpose.CLIENT_AUTH,
cafile='ca.crt'
)
ssl_context.load_cert_chain(
certfile='server.crt',
keyfile='server.key'
)
ssl_context.verify_mode = ssl.CERT_REQUIRED
with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as socket_fd:
try:
socket_fd.bind(("", PORT_NUMBER))
except Exception as e:
print(f"Unable to bind base socket. Reason:\n{e}")
return(-1)
socket_fd.listen(5)
with ssl_context.wrap_socket(socket_fd, server_side=True) as secure_socket_fd:
session_fd, client = secure_socket_fd.accept()
with session_fd:
print(f"Echoing {client}:")
while True:
try:
buffer = session_fd.recv(16)
except ConnectionResetError:
try:
session_fd.shutdown(socket.SHUT_RDWR)
except:
pass
else:
print("Client closed the connection\nSession shutdown successful...")
break
print(f"Message received!\n{buffer}")
session_fd.sendall(buffer)
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Must pass an address!\nExiting...")
sys.exit(-1)
else:
PORT_NUMBER = int(sys.argv[1])
sys.exit(main(PORT_NUMBER))
此配置会产生以下错误:
- 客户端:ssl.SSLCertVerificationError:[SSL:CERTIFICATE_VERIFY_FAILED]证书验证失败:自签名证书(_ssl.c:1123)
- 服务器:ssl.SSLError:[SSL:TLSV1_ALERT_UNKNOWN_CA] tlsv 1警报未知ca(_ssl.c:1056)
如果我在client.py的ssl.create_default_context()
中使用server.crt作为cafile
,在server.py的ssl.create_default_context()
中使用client.crt作为cafile
,则握手成功。
请注意,我已经根据Python的ssl指南尝试将CA连接到服务器和客户端crt。
1条答案
按热度按时间46qrfjad1#
我解决了:问题是CA的通用名与服务器的通用名相同。一旦我使用CA和服务器的不同通用名重新创建证书,它就工作了。我相信这可能是因为具有相同的通用名(因此不是CA与主题的唯一标识符)破坏了证书链的解析。