Ali*_*Ali 11 ssl python-3.x tls1.2
我想创建到服务器的 TLS 连接。然后,我想发送一些加密的数据到服务器。我知道主机名和端口并且有证书。令人惊讶的是,我还收到了服务器的私钥。但是,我认为我收到私钥是不正常的。
第一个问题是,我真的需要私钥来建立 TLS 连接吗?
顺便说一句,我正在使用这个 python 脚本
import socket
import ssl
server_addr = '**.**.**.**'
server_port = ****
server_cert = 'server.crt'
server_key = 'server.key' # I use the private key
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.verify_mode = ssl.CERT_REQUIRED
context.load_cert_chain(certfile=server_cert, keyfile=server_key)
bindsocket = socket.socket()
bindsocket.connect((server_addr, server_port))
Run Code Online (Sandbox Code Playgroud)
我在上面的脚本中使用私钥。它可以正常工作,没有任何错误。但是,当我尝试使用 bind() 而不是 connect() 时,即
bindsocket.bind((server_addr, server_port))
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
OSError: [Errno 99] 无法分配请求的地址
我已经阅读了许多有关上述错误的相关问题,但是,我仍然不明白为什么会发生这种情况。因为我有主机名、端口、证书和密钥,所以我希望能够成功创建 TLS 连接。
第二个问题是如何建立TLS连接?我的脚本正确吗?
我非常感谢任何改进脚本的评论。
toy*_*ian 14
所以,首先,你绝对不应该拥有私钥!顾名思义,它是私有的,不需要建立连接。
您可以拥有公钥,但即使如此,只要您使用标准 SSL 并且信任签署服务器证书的 CA,也没有必要。
你确定这是私钥吗?文件以 开头吗-----BEGIN PRIVATE KEY-----?检查与openssl rsa -noout -text -in server.key. 有关非对称加密的更多信息,
请参阅维基百科文章和这篇文章。
进一步:
将socket.bind()套接字绑定到本地计算机上的端口。这是不可能的,因为您的计算机没有地址(您提供服务器地址)。
从您的代码来看,您似乎正在尝试将套接字作为服务器打开。为此,您将需要私钥,但随后您将接受连接,而不会自己连接到其他计算机。我有一种感觉,你在这里混淆了两件事。
请参阅此问题的python 文档,因为这似乎密切相关。
另请查看有关 ssl 的 python 文档。我举了一个例子,它满足了您从所述文档中要求的内容:socket.bind()
import socket, ssl, pprint
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# require a certificate from the server
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())
# note that closing the SSLSocket will also close the underlying socket
ssl_sock.close()
Run Code Online (Sandbox Code Playgroud)
进一步的想法:
您真的需要自己完成所有 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)
# empty data means the client is finished with us
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()
Run Code Online (Sandbox Code Playgroud)
运行它:
% python3 ssltest.py
b'hello server!\n'
b'this is data\n'
Run Code Online (Sandbox Code Playgroud)
客户端:
% 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
Run Code Online (Sandbox Code Playgroud)
如果您使用一些常用协议(例如 HTTP),则应该使用库。这是一个使用烧瓶的示例:
>>> 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 -
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
35289 次 |
| 最近记录: |