简体   繁体   中英

Python load stored certificate private key

On a Windows server I'm trying to get the private key of a stored certificate.

On the server, I have:

  • The certificate stored in Local Machine My, installed from a PXF file as exportable.
  • Python 3.7.0
  • cryptography pip package version 37.0.2
  • Windows Server 2019

Problem:
My script fails to deserialize key data from the loaded PEM.
Note: I could successfully use the original certificate PFX file for the purpose it has been created for (authenticate to Azure)

code00.py:

import ssl
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes,serialization

expected_thumbprint = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

def hex_string_readable(bytes):
        return ["{:02X}".format(x) for x in bytes]

for c in ssl.enum_certificates("MY"):
    data = c[0]
    pem_data = ssl.DER_cert_to_PEM_cert(data).encode()

    cert_details = x509.load_pem_x509_certificate(pem_data, default_backend())

    fingerprint = hex_string_readable(cert_details.fingerprint(hashes.SHA1()))
    fingerprint_string = ''.join(fingerprint)
    print(fingerprint_string)
    if fingerprint_string == expected_thumbprint:
        print("Certificate found!")
        private_key = serialization.load_pem_private_key(pem_data, None, backend=default_backend())
        break

Result:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Certificate found!
Traceback (most recent call last):
  File ".\code00.py", line 22, in <module>
    private_key = serialization.load_pem_private_key(pem_data, None, backend=default_backend())
  File "C:\temp\.venv\lib\site-packages\cryptography\hazmat\primitives\serialization\base.py", line 22, in load_pem_private_key
    return ossl.load_pem_private_key(data, password)
  File "C:\temp\.venv\lib\site-packages\cryptography\hazmat\backends\openssl\backend.py", line 904, in load_pem_private_key
    password,
  File "C:\temp\.venv\lib\site-packages\cryptography\hazmat\backends\openssl\backend.py", line 1168, in _load_key
    self._handle_key_loading_error()
  File "C:\temp\.venv\lib\site-packages\cryptography\hazmat\backends\openssl\backend.py", line 1193, in _handle_key_loading_error
    "Could not deserialize key data. The data may be in an "
ValueError: Could not deserialize key data. The data may be in an incorrect format or it may be encrypted with an unsupported algorithm.

Is there anything I'm doing wrong or other ways to achieve this goal?
Thanks in advance.

I'm probably late to the party, but this might help to someone in the future.

In your code you are actually searching through loaded certificates from Windows Certificate Store. Ssl library loads those, but from what I could see, it loads only public part of the certificates. This is enough if you have TLS client which only authenticates server, but if you have two-way authentication or TLS server and you need to use Windows Certificate Store things get difficult.

The difficulty lies in the fact that Windows crypto API allows private key export only through one function which exports PFX format either into file or into memory. As you mentioned, you already have PFX file which includes private key. You can use that and load it into Python code with something like this:

with open("Cert.pfx", "rb") as pfxFile:
    pfxBinData = pfxFile.read()
    privateKey, cert, additionalCerts = pkcs12.load_key_and_certificates(pfxBinData, b"PFX_PASSWORD")

Result of this function gets you everything you need in order for other side to authenticate you . Private key is contained in privateKey variable obviously, and certificate chain you get by combining cert and additionalCerts.

If you need to load this into SSL context, one solution would be to use named pipes, as SSL context only allows loading of certificate chain and private key from files in PEM format. This is great for Linux, but quite a pain under Windows paired with its Certificate Store.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM