gpt4 book ai didi

python - 为什么这个 Python 代码不能通过 SSL 连接?

转载 作者:太空宇宙 更新时间:2023-11-03 13:37:00 25 4
gpt4 key购买 nike

已更新:问题底部的固定/工作代码。重新实现以使用 wrap_socket() 而不是 SSL.Context()。协商的密码似乎不受 ssl.PROTOCOL_

的影响

我有一个在端口 8388 上监听的 XML 服务。该服务有自己的内置 CA,并将为在其管理界面上配置的任何客户端发布一个 P12 文件(我需要在我的连接中包含一个 CA 证书) .

我已经配置了客户端并下载了P12文件;还从 P12 导出了 PEM 文件(以便于调试),并为服务器 CA(这是一个 Java keystore )导出了一个 PEM 文件。

如果我使用 openssl s_client 并将客户端证书/ key 和 CA 文件提供给它,似乎一切正常;即:验证 return:1 在下面截断的输出中。 openssl 进程不会在服务器上生成任何证书错误(我的 Python 脚本也是如此)。根据我的阅读,这应该意味着证书都正常且有效。

# openssl s_client -connect srv.domain.net:8388 -CAfile server_ca.pem  -cert client_cert.pem -key client_key.pem
CONNECTED(00000003)
depth=1 ... emailAddress = ca@SERVERsystems.com
verify return:1
depth=0 ...CN = srv.domain.net
verify return:1
---
Certificate chain
0 s:/emailAddress=help@mydomain.net...CN=srv.domain.net
i:/C=US/...emailAddress=ca@SERVERsystems.com
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIJRDCCByygAwIBAgIGAVGIopaoMA0GCSqGSIb3DQEBDQUAMIG...rV
-----END CERTIFICATE-----
subject=/emailAddress=help@mydomain.net...CN=srv.domain.net
issuer=/C=US/...emailAddress=ca@SERVERsystems.com
---
Acceptable client certificate CA names
/C=US/...emailAddress=ca@SERVERsystems.com
/.../CN=srv.domain.net
---
SSL handshake has read 3369 bytes and written 5705 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: ...DF6572FA00D62D83CF0B1A82F
Session-ID-ctx:
Master-Key: ...7F685C0B163A7739C271E9722FC0554108175C4
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1461337153
Timeout : 300 (sec)
Verify return code: 0 (ok)
---

我现在正尝试使用相同的证书、 key 和 CA 文件将 Python (2.7.9) 脚本连接到 XML 服务,但我无法让它工作。 Python 提示 SSLv3 错误,服务器说它无法验证客户端。因此,连接有效,但握手、证书或密码等不正确。

我已经搜索了很多示例和实现,而这个似乎是最简单的一个,所以我开始使用它作为模板。 SSL3 不是我会坚持使用的协议(protocol) (POODLE),但它应该来自一个工作示例,所以我想做尽可能少的更改以使事情正常工作,然后从那里进行调整。有人知道我在这里做错了什么吗?输出/错误/日志发布在最底部。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import socket
import OpenSSL
from OpenSSL import *
import sys

serverName = sys.argv[1]
print "Using server : " + serverName

ctx = SSL.Context(SSL.SSLv3_METHOD)

ctx.use_privatekey_file('client_key.pem')
ctx.use_certificate_file('client_cert.pem')
ctx.load_verify_locations(cafile='server_ca.pem')

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((serverName, 8388))
sslSocket = socket.ssl(s)

print repr(sslSocket.server())
print repr(sslSocket.issuer())

print ("writing socket..")
sslSocket.write('<transaction><data>14</data></transaction>\n')
s.close()

Python 输出:

Using server : localhost
Traceback (most recent call last):
File "./test3.py", line 29, in <module>
sslSocket = socket.ssl(s)
File "/usr/lib/python2.7/socket.py", line 64, in ssl
return _realssl.sslwrap_simple(sock, keyfile, certfile)
File "/usr/lib/python2.7/ssl.py", line 993, in sslwrap_simple
ssl_sock.do_handshake()
ssl.SSLError: [SSL: SSLV3_ALERT_BAD_CERTIFICATE] sslv3 alert bad certificate (_ssl.c:581)

上面连接后的服务器日志:

Apr 22 10:39:56 srv.domain.net ERROR server.auth [Thread-183,run:233] Couldn't validate the client certificate.  Verify the validity and dates of the client cert.
Apr 22 10:39:56 srv.domain.net javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
Apr 22 10:39:56 srv.domain.net at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:431)
Apr 22 10:39:56 srv.domain.net at com.xml.server.auth.run(auth.java:226)
Apr 22 10:39:56 srv.domain.net at java.lang.Thread.run(Thread.java:745)

工作代码:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import socket
import ssl
import sys
import os

serverName = sys.argv[1]
print "Using server : " + serverName

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# ssl.PROTOCOL_xxx does not seem to affect negotiated cipher??
wrapper = ssl.wrap_socket(s,
ca_certs = "server_ca.pem",
certfile = "client_cert.pem",
keyfile = "client_key.pem",
cert_reqs=ssl.CERT_REQUIRED,
ssl_version=ssl.PROTOCOL_TLSv1)

wrapper.connect((serverName, 8388))

# some info on the connnection/cipher in use
print repr(wrapper.getpeername())
print repr(wrapper.cipher())
print repr(wrapper.getpeercert())

# send server command
print ("writing socket..")
wrapper.send ("<transaction><data>14</data></transaction>\n")

# read server reply
print "server reply: " + wrapper.recv(4096)
wrapper.close()
s.close()

最佳答案

ctx.use_privatekey_file('client_key.pem')
ctx.use_certificate_file('client_cert.pem')
...
sslSocket = socket.ssl(s)

当您使用客户端证书创建 SSL 上下文时,您不会在 SSL 连接中使用此上下文。这意味着将不会发送客户端证书,并且服务器会相应地进行投诉。

使用客户端证书的一种更简单的方法是使用ssl.wrap_socketcertfilekeyfile 参数,参见the documentation .

关于python - 为什么这个 Python 代码不能通过 SSL 连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36798453/

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