Search code examples
python-3.xcryptographycertificatex509pem

x509 error with python 3.6 during read pem certificate


in my python code I am facing the following problem:

Traceback (most recent call last):
  File "/tmp/mod_wsgi-localhost:5000:0/handler.wsgi", line 94, in <module>
    recorder_directory=recorder_directory)
  File "/usr/lib64/python3.6/site-packages/mod_wsgi/server/__init__.py", line 1400, in __init__
    exec(code, self.module.__dict__)
  File "/app/scripts/core.wsgi", line 1, in <module>
    from core_nbi import core_ws as application
  File "/app/core_if_nbi.py", line 357, in <module>
    coreApi.start()
  File "/app/core.py", line 250, in wrapper
    return func(self, *args, **kwargs)
  File "/app/core.py", line 646, in start
    self.otkHandler.loadCertificate()
  File "/app/core.py", line 294, in loadCertificate
    default_backend())
  File "/usr/lib64/python3.6/site-packages/cryptography/x509/base.py", line 50, in load_pem_x509_certificate
    return backend.load_pem_x509_certificate(data)
  File "/usr/lib64/python3.6/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1143, in load_pem_x509_certificate
    mem_bio = self._bytes_to_bio(data)
  File "/usr/lib64/python3.6/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 454, in _bytes_to_bio
    data_ptr = self._ffi.from_buffer(data)
TypeError: from_buffer() cannot return the address of a unicode object

The code that is failing is the following:

            certificate = x509.load_pem_x509_certificate(
                certificate_file.read(),
                default_backend())
#               backend=default_backend())
            self.public_key = certificate.public_key()

To notice that with python 2.7 version this code worked. Now I have to change my python version and I have also updated modules as well. The certificate I am trying to read is a valid PEM certificate, starting with :

-----BEGIN CERTIFICATE-----
MIIFgjCCA2oCCQD7TLSQ/uU4AjANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMC
4y34NPO08tUuRauZvhejBWLlv1yC6UID0rLdkzjFd2x0hn326r3xaPMsD7BMZVXy
................................................................
O6dZxMeQwKIuDy1lQPTyleDIdKTSTX55/Dug7ey3/Ayl7Bw63H9rlEtKy8VONJrl
9G1sJf9MoktA9uPfMk0EU9B0CZzUUQ==
-----END CERTIFICATE-----
Package        Version  
-------------- ---------
aniso8601      7.0.0    
appdirs        1.4.3    
asn1crypto     0.24.0   
avro-python3   1.9.0    
bcrypt         3.1.7    
certifi        2019.6.16
cffi           1.12.3   
chardet        3.0.4    
Click          7.0      
cryptography   2.7      
Flask          0.12.1   
Flask-HTTPAuth 3.2.2    
Flask-RESTful  0.3.5    
idna           2.6      
itsdangerous   1.1.0    
Jinja2         2.10.1   
kafka-python   1.4.3    
MarkupSafe     1.1.1    
mod-wsgi       4.5.18   
netmiko        2.4.0    
packaging      16.8     
paramiko       2.6.0    
pip            19.1.1   
pycparser      2.19     
PyJWT          1.5.2    
pymongo        3.6.0    
PyNaCl         1.3.0    
pyparsing      2.2.0    
pyserial       3.4      
pytz           2019.1   
PyYAML         5.1.1    
requests       2.18.4   
scp            0.13.2   
setuptools     38.4.1   
six            1.11.0   
textfsm        0.4.1    
urllib3        1.22     
Werkzeug       0.15.5   

pip 19.1.1 from /usr/lib/python3.6/site-packages/pip (python 3.6)

Do you know how to fix the problem?


Solution

  • load_pem_x509_certificate takes bytes, not a string. In Python 2.7 this distinction was irrelevant, but in 3.x you must encode it to bytes first. Since you're reading this from a file the best solution is to change your open call to use rb (read binary) as the mode and then the certificate_file.read() will return bytes.