我正在尝试使用单个 .pfx 文件进行身份验证创建 SSL 客户端。但是,在Python中使用load_cert_chain时遇到以下错误: [SSL] PEM 库 (_ssl.c:3862)
我正在从 .pfx 文件加载私钥和证书并将其转换为 PEM 格式。我希望这种方法能够成功验证客户端身份,但我不断收到此错误。这是我正在使用的代码:
import ssl
import tempfile
from cryptography.hazmat.primitives.serialization.pkcs12 import
load_key_and_certificates
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.serialization import Encoding,
PrivateFormat, NoEncryption
with open(pfx_file, 'rb') as f:
pfx_data = f.read()
private_key, certificate, additional_certificates = load_key_and_certificates(
pfx_data,
pfx_password.encode(),
backend=default_backend()
)
pem_private_key = private_key.private_bytes(
encoding=Encoding.PEM,
format=PrivateFormat.PKCS8,
encryption_algorithm=NoEncryption()
)
pem_certificate = certificate.public_bytes(Encoding.PEM)
with tempfile.NamedTemporaryFile(suffix='.pem', delete=False) as certfile,
tempfile.NamedTemporaryFile(suffix='.pem', delete=False) as keyfile:
certfile.write(pem_certificate)
keyfile.write(pem_private_key)
context = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)
context.load_cert_chain(certfile=certfile.name, keyfile=keyfile.name)
我也使用OpenSSL库尝试了以下方法,但遇到了同样的问题: 上下文 = SSL.Context(SSL.TLSv1_2_METHOD)
您需要刷新两个临时文件的写入缓冲区。 对于如此少量的数据,在上下文关闭或刷新缓冲区之前,内容不会写入磁盘。
with (tempfile.NamedTemporaryFile(suffix='.pem', delete=False) as certfile,
tempfile.NamedTemporaryFile(suffix='.pem', delete=False) as keyfile):
certfile.write(pem_certificate)
keyfile.write(pem_private_key)
certfile.flush()
keyfile.flush()
context = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)
context.load_cert_chain(certfile=certfile.name, keyfile=keyfile.name)
如果您设置
delete=True
并尝试从临时文件文件路径读取,则可能会遇到权限错误。 Windows 似乎根本不喜欢这样。 作为解决方法,您可以创建一个临时目录,将文件写入其中,关闭时文件将被删除。
with tempfile.TemporaryDirectory() as certdir:
certfile = f'{certdir}/cert.pem'
keyfile = f'{certdir}/key.pem'
with open(certfile, 'wb') as fp:
fp.write(pem_certificate)
with open(keyfile, 'wb') as fp:
fp.write(pem_private_key)
context = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)
context.load_cert_chain(certfile=certfile, keyfile=keyfile)