使用Python ssl库时出现“SSLError: [SSL] PEM lib (_ssl.c:2532)”是什么意思?

问题描述 投票:0回答:6

我尝试使用 Python 3 asyncio 模块连接到另一方并收到此错误:

     36     sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
---> 37     sslcontext.load_cert_chain(cert, keyfile=ca_cert)
     38

SSLError: [SSL] PEM lib (_ssl.c:2532)

问题只是错误的含义。我的证书是正确的,密钥文件(CA 证书)可能不正确

python python-3.x ssl ssl-certificate python-asyncio
6个回答
38
投票

假设使用的是3.6版本:

参见:https://github.com/python/cpython/blob/3.6/Modules/_ssl.c#L3523-L3534

 PySSL_BEGIN_ALLOW_THREADS_S(pw_info.thread_state);
 r = SSL_CTX_check_private_key(self->ctx);
 PySSL_END_ALLOW_THREADS_S(pw_info.thread_state);
 if (r != 1) { 
    _setSSLError(NULL, 0, __FILE__, __LINE__);
    goto error;
 }

它的意思是

SSL_CTX_check_private_key
失败了;因此,私钥不正确。

参考可能的版本:


22
投票

在您的代码中,您正在调用:

sslcontext.load_cert_chain(cert, keyfile=ca_cert)

来自文档

加载私钥和对应的证书。证书文件 string 必须是 PEM 格式的单个文件的路径,其中包含 证书以及所需的任意数量的 CA 证书 确定证书的真实性。密钥文件字符串,如果 存在,必须指向包含私钥的文件。否则 私钥也将从 certfile 中获取。请参阅 证书的讨论以获取有关证书如何使用的更多信息 存储在 certfile 中。

根据示例中的参数名称,您似乎正在将 CA 证书传递给

keyfile
参数。 这是不正确的,您需要传入用于生成本地证书的私钥(否则客户端无法使用您的证书)。 私钥文件看起来像:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,9BA4973008F0A0B36FBE1426C198DD1B

...data...
-----END RSA PRIVATE KEY-----

仅当您尝试验证由此证书签名的 SSL 证书的有效性时,才需要 CA 证书。 在这种情况下,您可能会使用

SSLContext.load_verify_locations()
来加载 CA 证书(尽管我最近没有使用过 SSL 模块,所以不要相信我的话)。


9
投票

该错误表示私钥文件丢失。 在 openssl shell 中生成密钥对: openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365

启动Python SSL服务器:

from http.server import HTTPServer, 
             SimpleHTTPRequestHandler

import ssl

httpd = HTTPServer(('localhost', 4443), 
                           SimpleHTTPRequestHandler)

httpd.socket = ssl.wrap_socket(httpd.socket, 
                 certfile='/tmp/cert.pem',keyfile='
                           /tmp/key.pem', server_side=True)

httpd.serve_forever()

(我们使用端口 4443,以便我可以以普通用户身份运行测试;通常的端口 443 需要 root 权限)。


4
投票

就我而言,此错误意味着我的证书的文件扩展名错误。我必须使用以下命令将我的

cert.der
文件转换为
cert.pem
文件:

openssl x509 -inform der -in cert.der -out cert.pem 

2
投票

在使用 openssl 生成受密码保护的自签名证书时,我遇到了类似的问题,得到以下输出:

ontext.load_cert_chain(certfile= certificate_private, keyfile= certificate)
ssl.SSLError: [SSL] PEM lib (_ssl.c:4012)

阅读两次以了解 load_cert_chain 上的文档后,我想出了以下解决方案:

import ssl
    
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.load_cert_chain(certfile= certificate_private, keyfile= certificate_key, password= certificate_password)

connection = http.client.HTTPSConnection(host, port=443, context=context)
connection.request(method="POST", url=request_url, headers=request_headers, body=json.dumps(request_body_dict))
response = connection.getresponse()

证书文件是

cert.pem

密钥文件是
key.pem

密码是我在生成自签名证书时使用的密码,类似于此答案中所述。


0
投票

在我的情况下,我们有一些使用 mTLS 连接到主机的代码。

load_cert_chain

方法是将客户端证书密钥对提供给 SSL 连接工厂的方式。

这个特定的应用程序在 Python 3.9 中运行。  当我们将运行时升级到 3.12 时,我们遇到了与问题中的错误类似的错误: 

SLError: [SSL] PEM lib (_ssl.c:XXXX)

它指向的特定行号用途有限,除非您确切知道您正在使用的 _ssl.c 版本。

无论如何,如果您的私钥已加密并且解密存在问题(例如密码不正确),则似乎会发生此错误。  然而,在我们的例子中,这不是问题。  问题似乎在于 OpenSSL 不再支持用于保护私钥的加密方法,至少默认情况下不支持。

我主要是通过猜测和反复试验才发现这一点的。 基本上,我解密了密钥文件并使用相同的密码重新加密,问题就解决了。

我无法找到任何说明 OpenSSL 支持或已删除哪些密钥加密/解密方法的信息。 希望这对其他人有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.