Reputation: 1
I am trying to create an SSL client using a single .pfx file for authentication. However, I am encountering the following error when using load_cert_chain in Python: [SSL] PEM lib (_ssl.c:3862)
I am loading the private key and certificate from the .pfx file and converting them to PEM format. I expected this approach to successfully authenticate the client, but I keep receiving this error. Here’s the code I am using:
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)
I also tried the following method using the OpenSSL library, but encountered the same issue: context = SSL.Context(SSL.TLSv1_2_METHOD)
Upvotes: 0
Views: 101
Reputation: 36756
You need to flush the write buffer for both tempfiles. For such small amount of data, the contents are not written to disk until the context is closed or the buffer is flushed.
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)
You might run into permission errors if you set delete=True
and try to read from the tempfile file path. Windows seems to not like that at all. As a work-around, you can create a temporary directory, write the files into that, and on closing the files will be deleted.
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)
Upvotes: 1