gpt4 book ai didi

python - 简单 ECHO 客户端/服务器 [Python/sockets/ssl 模块] 中的相互 ssl 身份验证,ssl.SSLEOFError : EOF occurred in violation of protocol

转载 作者:太空狗 更新时间:2023-10-29 17:33:04 25 4
gpt4 key购买 nike

我想在我的 echo 客户端/服务器程序中进行相互验证。我在

上使用 python 2.7.12 和 ssl` 模块
Distributor ID: Ubuntu
Description: Ubuntu 14.04.5 LTS
Release: 14.04
Codename: trusty

我已经使用 openssl 命令生成了客户端和服务器的证书和 key :

openssl req -new -x509 -days 365 -nodes -out client.pem -keyout client.key
openssl req -new -x509 -days 365 -nodes -out server.pem -keyout server.key

我希望客户端对服务器进行身份验证,我希望服务器对客户端进行身份验证。但是,下面的代码在服务器端显示了一些错误:

Traceback (most recent call last):
File "ssl_server.py", line 18, in <module>
secure_sock = ssl.wrap_socket(client, server_side=True, certfile="server.pem", keyfile="server.key")
File "/usr/lib/python2.7/ssl.py", line 933, in wrap_socket
ciphers=ciphers)
File "/usr/lib/python2.7/ssl.py", line 601, in __init__
self.do_handshake()
File "/usr/lib/python2.7/ssl.py", line 830, in do_handshake
self._sslobj.do_handshake()
ssl.SSLEOFError: EOF occurred in violation of protocol (_ssl.c:590)

在客户端:

Traceback (most recent call last):
File "ssl_client.py", line 18, in <module>
secure_sock = context.wrap_socket(sock, server_hostname=HOST, server_side=False, certfile="client.pem", keyfile="client.key")
TypeError: wrap_socket() got an unexpected keyword argument 'certfile'

服务器代码:

#!/bin/usr/env python
import socket
import ssl
import pprint

#server
if __name__ == '__main__':

HOST = '127.0.0.1'
PORT = 1234

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen(10)

client, fromaddr = server_socket.accept()
secure_sock = ssl.wrap_socket(client, server_side=True, certfile="server.pem", keyfile="server.key")

print repr(secure_sock.getpeername())
print secure_sock.cipher()
print pprint.pformat(secure_sock.getpeercert())
cert = secure_sock.getpeercert()
print cert

# verify client
if not cert or ('commonName', 'test') not in cert['subject'][4]: raise Exception("ERROR")

try:
data = secure_sock.read(1024)
secure_sock.write(data)
finally:
secure_sock.close()
server_socket.close()

客户代码:

import socket
import ssl

# client
if __name__ == '__main__':

HOST = '127.0.0.1'
PORT = 1234

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))

context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
context.verify_mode = ssl.CERT_REQUIRED
context.load_verify_locations('server.pem')

if ssl.HAS_SNI:
secure_sock = context.wrap_socket(sock, server_hostname=HOST, server_side=False, certfile="client.pem", keyfile="client.key")
else:
secure_sock = context.wrap_socket(sock, server_side=False, certfile="client.pem", keyfile="client.key")

cert = secure_sock.getpeercert()
print cert

# verify server
if not cert or ('commonName', 'test') not in cert['subject'][4]: raise Exception("ERROR")

secure_sock.write('hello')
secure_sock.read(1024)

secure_sock.close()
sock.close()

谢谢。

最佳答案

基本上服务器需要与客户端共享他的证书,反之亦然(查看ca_certs 参数)。您的代码的主要问题是从未执行过握手。此外,Common Name 字符串位置取决于证书中指定的字段数。我比较懒,所以我的 subject 只有 4 个字段,Common Name 是最后一个。

现在可以使用了(请随时询问更多详细信息)。

服务器

#!/bin/usr/env python
import socket
import ssl
import pprint

#server
if __name__ == '__main__':

HOST = '127.0.0.1'
PORT = 1234

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen(10)

client, fromaddr = server_socket.accept()
secure_sock = ssl.wrap_socket(client, server_side=True, ca_certs = "client.pem", certfile="server.pem", keyfile="server.key", cert_reqs=ssl.CERT_REQUIRED,
ssl_version=ssl.PROTOCOL_TLSv1_2)

print repr(secure_sock.getpeername())
print secure_sock.cipher()
print pprint.pformat(secure_sock.getpeercert())
cert = secure_sock.getpeercert()
print cert

# verify client
if not cert or ('commonName', 'test') not in cert['subject'][3]: raise Exception("ERROR")

try:
data = secure_sock.read(1024)
secure_sock.write(data)
finally:
secure_sock.close()
server_socket.close()

客户端

import socket
import ssl

# client
if __name__ == '__main__':

HOST = '127.0.0.1'
PORT = 1234

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(1);
sock.connect((HOST, PORT))

context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
context.verify_mode = ssl.CERT_REQUIRED
context.load_verify_locations('server.pem')
context.load_cert_chain(certfile="client.pem", keyfile="client.key")

if ssl.HAS_SNI:
secure_sock = context.wrap_socket(sock, server_side=False, server_hostname=HOST)
else:
secure_sock = context.wrap_socket(sock, server_side=False)

cert = secure_sock.getpeercert()
print cert

# verify server
if not cert or ('commonName', 'test') not in cert['subject'][3]: raise Exception("ERROR")

secure_sock.write('hello')
print secure_sock.read(1024)

secure_sock.close()
sock.close()

看看:

Proof

Ps: 我让客户端打印服务器响应。

回复评论

On client's side you never used the context variable I've created. Does it mean it's unnecessary here?

文档说:

For more sophisticated applications, the ssl.SSLContext class helps manage settings and certificates, which can then be inherited by SSL sockets created through the SSLContext.wrap_socket() method.

我更新了代码以向您展示差异:服务器使用 ssl.wrap_socket(),客户端使用 ssl.SSLContext.wrap_socket()

Second, what's the point in checking if ssl.HAS_SNI when the socket creation looks the same in if and else? With your approach I cant use server_hostname=HOST in socket wrapping method.

你是对的,在更新后的代码中我使用了 server_hostname=HOST

Another thing: you're using ca_certs instead of using load_verify_locations in context I created. Why? Are those 2 methods identical?

我的错,我使用 ca_cert 作为 ssl.wrap_socket() 的参数,所以我根本没有使用 context .现在我在用它。

And another thing: do you really need to call secure_sock.do_handshake() by yourself?

不,我忘了删除它:)

输出完全一样。

关于python - 简单 ECHO 客户端/服务器 [Python/sockets/ssl 模块] 中的相互 ssl 身份验证,ssl.SSLEOFError : EOF occurred in violation of protocol,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44343230/

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