首先,绝不能拥有私钥!正如其名称所示,它是私有的,不必要用于建立连接。
你可以拥有公钥,但只要使用标准 SSL 并信任签署服务器证书的 CA,甚至公钥也不是必需的。
你确定它是私钥吗?文件是否以 -----BEGIN PRIVATE KEY-----
开头?请使用openssl rsa -noout -text -in server.key
进行检查。
有关非对称加密的更多信息,请参阅维基百科文章和此帖子。
下一步:
通过 socket.bind()
,你将套接字绑定到本地机器上的某个端口。这是不可能的,因为你没有地址(你提供了服务器地址)。
从你的代码中看,你似乎正在尝试以服务器身份打开套接字。你将需要私钥才能这样做,但随后你将接受连接而不是自己连接其他机器。我有一种感觉,你在把两件事情搞混了。
有关 socket.bind()
的详细信息,请参阅Python 文档,有关此问题的信息,请参阅此问题,因为这似乎与之密切相关。
还请查看Python SSL 文档。我从该文档中选取了一个符合你要求的示例。
import socket, ssl, pprint
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = ssl.wrap_socket(s,
ca_certs="/etc/ca_certs_file",
cert_reqs=ssl.CERT_REQUIRED)
ssl_sock.connect(('www.verisign.com', 443))
pprint.pprint(ssl_sock.getpeercert())
ssl_sock.close()
另外请参考如何在服务器模式下打开SSL套接字的示例。
进一步思考:
你真的需要自己完成所有的TLS工作吗?如果服务器,例如使用HTTPS (SSL加密的HTTP),则可以使用http.client库。
如果需要我澄清某些内容,请随时询问。我将相应地更新我的答案。
编辑:
由于您表示希望以服务器模式打开端口,因此我为您制作了一个示例(它严重依赖于Python文档示例):
import socket, ssl
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
context.load_cert_chain(certfile="cert.pem", keyfile="key.pem")
bindsocket = socket.socket()
bindsocket.bind(('127.0.0.1', 10023))
bindsocket.listen(5)
def deal_with_client(connstream):
data = connstream.recv(1024)
while data:
print(data)
data = connstream.recv(1024)
while True:
newsocket, fromaddr = bindsocket.accept()
connstream = context.wrap_socket(newsocket, server_side=True)
try:
deal_with_client(connstream)
finally:
connstream.shutdown(socket.SHUT_RDWR)
connstream.close()
运行它:
% python3 ssltest.py
b'hello server!\n'
b'this is data\n'
客户端:
% openssl s_client -connect 127.0.0.1:10023
CONNECTED(00000005)
depth=0 C = SE, ST = Some-State, O = Internet Widgits Pty Ltd
verify error:num=18:self signed certificate
verify return:1
depth=0 C = SE, ST = Some-State, O = Internet Widgits Pty Ltd
verify return:1
---
Certificate chain
0 s:C = SE, ST = Some-State, O = Internet Widgits Pty Ltd
i:C = SE, ST = Some-State, O = Internet Widgits Pty Ltd
---
Server certificate
-----BEGIN CERTIFICATE-----
... certificate ...
-----END CERTIFICATE-----
subject=C = SE, ST = Some-State, O = Internet Widgits Pty Ltd
issuer=C = SE, ST = Some-State, O = Internet Widgits Pty Ltd
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 2272 bytes and written 404 bytes
Verification error: self signed certificate
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 4096 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
... session stuff ...
Extended master secret: yes
---
hello server!
this is data
^C
如果您使用像HTTP这样的常用协议,建议使用库来实现。以下是使用Flask的示例:
>>> from flask import Flask
>>> app = Flask(__name__)
>>>
>>> @app.route("/")
... def hello():
... return "Hello World!"
...
>>> if __name__ == "__main__":
... app.run(ssl_context=('cert.pem', 'key.pem'))
...
* Serving Flask app "__main__" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on https://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [06/Aug/2020 11:45:50] "GET / HTTP/1.1" 200 -
openssl s_client
命令时,一切都很顺利,我可以向服务器发送数据。然而,当我尝试使用Python代码(客户端)发送一些数据时,它失败了。这是发送数据到服务器的Python代码:https://stackoverflow.com/q/63326571/9696715 - Ali