[python-win32] win32crypt.PFXImportCertStore()
Steven Manross
steven at manross.net
Sun Sep 22 16:13:36 EDT 2024
Howdy,
I am trying to import a PFX/P12 certificate to the local machine certificate store and there’s no errors, but it also doesn’t seem to work either.
I’ve left a bit of debugging code in the script to show all the things I’ve tried, but again there’s no errors, and it generates the PyStore object like the docs say it will and I enumerate the certificates in the store with a for loop, BUT it doesn’t seem to add the PFX to the store (or at least I can’t see it in the Certificates MMC app for the local machine).
I can manually import the PFX by using the CryptoAPI “Install PFX” option from the windows explorer shell just fine, but the win32crypt.PFXImportCertStore() call doesn’t error, but it also enumerates the machine store certs without the “newly added” PFX.
# this is output from the script in the for loop at the bottom from the attached python script – these 2 certificates existed prior to the PFX trying to get imported
1 Cert: <PyCERT_CONTEXT object at 0x000001D0103736B0>
2 CertEnumCertificateContextProperties returned: []
3 cert.Subject: w22test001.manross.net
4 cert Serial Number: redacted
5 Issuer: redacted
6 NotBefore: redacted
7 NotAfter: redacted
1 Cert: <PyCERT_CONTEXT object at 0x000001D010373920>
2 CertEnumCertificateContextProperties returned: [2, 11]
3 cert.Subject: w22test001.manross.net
4 cert Serial Number: redacted
5 Issuer: redacted
6 NotBefore: redacted
7 NotAfter: redacted
Please and thank you,
Steven
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.python.org/pipermail/python-win32/attachments/20240922/efe1feec/attachment.html>
-------------- next part --------------
# ran on Windows Server 2022, and Windows Server 2016 (can test Windows Server 2019 if needed)
# Python 3.11.9 (tags/v3.11.9:de54cf5, Apr 2 2024, 10:12:12) [MSC v.1938 64 bit (AMD64)]
# pywin32==306
import win32crypt
import getpass
import datetime
CERT_STORE_PROV_SYSTEM = 0x0000000A
CERT_SYSTEM_STORE_LOCAL_MACHINE = 0x00020000
CERT_STORE_MAXIMUM_ALLOWED_FLAG = 0x00001000
X509_ASN_ENCODING= 0x00000001
PKCS_7_ASN_ENCODING= 0x00010000
PKCS_7_OR_X509_ASN_ENCODING= PKCS_7_ASN_ENCODING | X509_ASN_ENCODING
CERT_STORE_ADD_NEW = 1
CRYPT_STRING_BASE64HEADER = 0x00000000
CERT_STORE_ADD_REPLACE_EXISTING = 3
CRYPT_EXPORTABLE = 0x00000001
CRYPT_MACHINE_KEYSET = 0x00000020
def import_certificate_to_the_windows_certificate_store_for_local_machine(cert_file_name, password):
# open and read the cert
cert_file = open(cert_file_name, "rb")
p12_data = cert_file.read() # this is a P12/PFX file that is secured by a password
# crypt the cert to the expected type
# Don't need this for PFXs (I think) because its already bytes (from the loaded p12_data -- opened from file)
# cert_byte = win32crypt.CryptStringToBinary(p12_data, 0x00000000)[0]
# # Add the certificate to the store (wrong kind of import for this -- just a certificate without the P12/PFX encoding/encryption/password)
# store.CertAddEncodedCertificateToStore(
# X509_ASN_ENCODING,
# p12_data,
# CERT_STORE_ADD_REPLACE_EXISTING
# )
# https://timgolden.me.uk/pywin32-docs/win32crypt__PFXImportCertStore_meth.html
# constants: https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-pfximportcertstore
# imports to the store because of CRYPT_MACHINE_KEYSET
store = win32crypt.PFXImportCertStore(p12_data, password, CRYPT_EXPORTABLE | CRYPT_MACHINE_KEYSET | PKCS12_INCLUDE_EXTENDED_PROPERTIES)
# the previous call creates a store object so this isn’t needed - open the LOCAL_LACHINE "Personal" certificates store
# store = win32crypt.CertOpenStore(
# CERT_STORE_PROV_SYSTEM,
# 0,
# None,
# CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_MAXIMUM_ALLOWED_FLAG,
# "My"
# )
# however, even though the store enumerates, it doesn’t show the PFX that was just imported
for mscert in store.CertEnumCertificatesInStore():
print( "1 Cert: {0:}".format(mscert))
print( "2 CertEnumCertificateContextProperties returned: {0:}".format(mscert.CertEnumCertificateContextProperties()))
print( "3 cert.Subject: {0:}".format(win32crypt.CertNameToStr(mscert.Subject)))
print(f"4 cert Serial Number: {mscert.SerialNumber.hex()}")
print(f"5 Issuer: {win32crypt.CertNameToStr(mscert.Issuer)}")
print(f"6 NotBefore: {datetime.datetime.fromtimestamp(mscert.NotBefore.timestamp()).astimezone(mscert.NotBefore.tzinfo)}")
print(f"7 NotAfter: {datetime.datetime.fromtimestamp(mscert.NotAfter.timestamp()).astimezone(mscert.NotAfter.tzinfo)}")
print()
if __name__ == "__main__":
cert_file_name = f"c:\\scripts\\certs\\w22test001.manross.net-winrm.pfx"
password = getpass.getpass(prompt="PFX Password:", stream=None)
import_certificate_to_the_windows_certificate_store_for_local_machine(cert_file_name, password)
More information about the python-win32
mailing list