在python中验证Peer

时间:2017-07-14 16:53:14

标签: python sockets ssl pyopenssl

我正在尝试使用python创建套接字连接。

这是我的python代码......

socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.settimeout(config['timeout'])
self.socket.connect((config['host'], config['port']))

self.ssl = ssl.wrap_socket(
    self.socket,
    certfile=config['certificate'],
    keyfile=config['key']
)

它不起作用,因为远程服务器的证书似乎是自签名或信任存储中丢失的。我是python的新手,无法弄清楚如何在python中禁用verify_peer,因此连接可以正常工作。

我在php中有工作代码......

$context = stream_context_create([
    'ssl' => [
        'verify_peer' => false,
        'local_cert' => $config['certificate'],
        'local_pk' => $config['key']
    ]
]);

$socket = stream_socket_client(
    'ssl://secure.test.com:700',
    $errno, $errstr, $config['timeout'],
    STREAM_CLIENT_CONNECT, $context
);

设置'verify_peer' => false有助于建立连接。我怎么能在python中做那样的事情?

openssl debug

openssl s_client -connect secure.test.com:700

verify error:num=20:unable to get local issuer certificate
verify return:1

verify error:num=21:unable to verify the first certificate
verify return:1

请帮忙并提出建议。感谢

1 个答案:

答案 0 :(得分:0)

只需添加cert_reqs = ssl.CERT_NONE即可停用证书验证。但是,只有禁用证书验证是一个非常糟糕的主意,因为您知道对man-in-the-middle attacks 开放。

因此,您应该检查证书是否是预期的证书。使用自签名证书(以及其他证书),您可以检查收到的证书是否与预期的证书指纹匹配,如下面的代码所示:

import socket
import ssl
import hashlib

dst = ('www.paypal.com',443)
fp_expected = '0722d46c216327bab8075f5db57ebed64d80e6699204c249c3f6ea9cc281c15b'

# connect to the target with TCP
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(dst)

# upgrade the socket to SSL without checking the certificate
s = ssl.wrap_socket(s,cert_reqs = ssl.CERT_NONE)

# get certificate, compute fingerprint and check against expected value
cert_bin = s.getpeercert(True)
fp = hashlib.sha256()
fp.update(cert_bin)
assert(fp.hexdigest() == fp_expected)