27

在 Python 中, ssl.wrap_socket 可以从文件中读取证书, ssl.wrap_socket 需要证书作为文件路径。

如何使用从字符串变量读取的证书启动 SSL 连接?

我的主机环境不允许写入文件,并且 tempfile 模块不起作用
我使用的是 Python 2.7。
我将证书存储在 MySQL 中并作为字符串读取。

编辑:我放弃了,这基本上是要求用纯python代码实现ssl,这超出了我目前的知识。

4

4 回答 4

28

查看源代码, ssl.wrap_socket 直接调用本机代码(openssl)函数 SSL_CTX_use_cert_chain_file ,该函数需要文件路径,因此您尝试做的事情是不可能的。

以供参考:

在 ssl/ init .py 我们看到:

def wrap_socket(sock, keyfile=None, certfile=None,
                server_side=False, cert_reqs=CERT_NONE,
                ssl_version=PROTOCOL_SSLv23, ca_certs=None,
                do_handshake_on_connect=True):

    return SSLSocket(sock, keyfile=keyfile, certfile=certfile,
                   server_side=server_side, cert_reqs=cert_reqs,
                   ssl_version=ssl_version, ca_certs=ca_certs,
                   do_handshake_on_connect=do_handshake_on_connect)

将我们指向 SSLSocket 构造函数(在同一个文件中),我们看到发生了以下情况:

self._sslobj = _ssl2.sslwrap(self._sock, server_side,
                                     keyfile, certfile,
                                     cert_reqs, ssl_version, ca_certs)

_ssl2 在 C 中实现 (_ssl2.c)

查看 sslwrap 函数,我们看到它正在创建一个新对象:

    return (PyObject *) newPySSLObject(Sock, key_file, cert_file,
                                       server_side, verification_mode,
                                       protocol, cacerts_file);

查看该对象的构造函数,我们最终看到:

            ret = SSL_CTX_use_certificate_chain_file(self->ctx,
                                                     cert_file);

该函数在 openssl 中定义,所以现在我们需要切换到该代码库。

在 ssl/ssl_rsa.c 我们最终在函数中找到:

BIO_read_filename(in,file) 

如果你深入研究 BIO 代码(openssl 的一部分),你最终会得到一个正常的 fopen():

fp=fopen(ptr,p);

所以它看起来就像现在写的一样。它必须在 C 的 fopen() 可打开的文件中。

此外,由于 python 的 ssl 库如此迅速地跳转到 C 中,我也没有看到一个明显的地方可以在解决方法中使用monkeypatch。

于 2012-12-16T21:53:10.193 回答
5

快速查看 ssl 模块源确认 API 不支持您想要的内容: http ://code.google.com/codesearch#2T6lfGELm_A/trunk/Modules/_ssl.c&q=sslwrap&type=cs

这并不是说不可能,您可以创建一个命名管道,从 Python 提供一端并将文件名提供给 ssl 模块。

为了更简单、更不安全的使用,将证书从内存转储到 mkstemp()'d 文件。

您甚至可以挂载 FUSE 卷并拦截文件回调。

最后,使用 ctypes 在运行时破解 ssl 上下文,并按照 C 配方从缓冲区中加载 cert/ket 从内存而不是使用 OpenSSL 的文件中读取证书文件以前已经做过类似的事情,但这并不是为了最胆小的人.

看起来您正试图摆脱例如应用程序引擎的“监狱”,也许这是不可能的?

如果你对 ssl 实现不挑剔,你可以使用 M2Crypto、TLS Lite、pyOpenSSL 或其他东西。较早的是纯python,您绝对可以破解它以使用内存中的证书/密钥。

于 2012-12-19T19:55:51.687 回答
3

从 Python 3.4 开始,您可以使用 SSLContext#load_verify_locations:

context = ssl.SSLContext()
context.load_verify_locations(cadata=cert)  # Where cert is str.

来自https://docs.python.org/3/library/ssl.html#ssl.SSLContext.load_verify_locations

于 2018-09-25T06:21:32.333 回答
-2

您可以使用StringIO将字符串视为文件。

于 2012-09-09T23:48:43.570 回答