I have a user certificate in the Personal/My Windows Store with an exportable private key. I am trying to export this in Python to use as .cer/.pem and secret key files in an API request. I have toyed around with several different solutions online involving the cryptography, win32api, win32crypt, ssl, and OpenSSL libraries. Nothing I have tried seems to work to successfully export the certificate from the store directly as a .cer/.pem and key, or as a .pfx to then extract these modules out of.
I have a working solution in which I am executing a subprocess with Powershell to leverage the Export-PfxCertificate CMDlet, then extracting the public and private bytes of the subsequent PFX using the cryptography standard library. I am hoping there is a solution to eliminate the need to subprocess out to Powershell. This is my current code in which I am hoping to replace lines 3-11:
<code>logging.info('Exporting the certificate from the cert store...')
transient_password = 'transient'
command = f'''$env:PSModulePath = [Environment]::GetEnvironmentVariable('PSModulePath', 'Machine');
$secret = ConvertTo-SecureString -String {transient_password} -Force -AsPlainText;
Export-PfxCertificate -Cert (Get-ChildItem -Path {CERT_PATH}) -FilePath caccpprod.pfx -Password $secret
child = subprocess.run(['powershell', '-command', command], capture_output = True)
if (child.returncode != 0):
logging.error(f'Encountered an error exporting the Windows Store cert to a PFX: {child.stderr.decode("UTF-8")}')
with open('caccpprod.pfx', 'rb') as pfx_file:
private_key, serial, chain = pkcs12.load_key_and_certificates(
transient_password.encode(),
with open(CER_FILE, 'wb') as cer_file:
cer_file.write(serial.public_bytes(serialization.Encoding.PEM))
with open(KEY_FILE, 'wb') as key_file:
key_file.write(private_key.private_bytes(
encoding = serialization.Encoding.PEM,
format = serialization.PrivateFormat.PKCS8,
encryption_algorithm = serialization.NoEncryption()
logging.info('Exported the certificate into .cer and .key files')
return CER_FILE, KEY_FILE
<code>logging.info('Exporting the certificate from the cert store...')
transient_password = 'transient'
command = f'''$env:PSModulePath = [Environment]::GetEnvironmentVariable('PSModulePath', 'Machine');
$secret = ConvertTo-SecureString -String {transient_password} -Force -AsPlainText;
Export-PfxCertificate -Cert (Get-ChildItem -Path {CERT_PATH}) -FilePath caccpprod.pfx -Password $secret
'''
child = subprocess.run(['powershell', '-command', command], capture_output = True)
if (child.returncode != 0):
logging.error(f'Encountered an error exporting the Windows Store cert to a PFX: {child.stderr.decode("UTF-8")}')
return False, False
with open('caccpprod.pfx', 'rb') as pfx_file:
private_key, serial, chain = pkcs12.load_key_and_certificates(
pfx_file.read(),
transient_password.encode(),
default_backend()
)
with open(CER_FILE, 'wb') as cer_file:
cer_file.write(serial.public_bytes(serialization.Encoding.PEM))
with open(KEY_FILE, 'wb') as key_file:
key_file.write(private_key.private_bytes(
encoding = serialization.Encoding.PEM,
format = serialization.PrivateFormat.PKCS8,
encryption_algorithm = serialization.NoEncryption()
))
logging.info('Exported the certificate into .cer and .key files')
return CER_FILE, KEY_FILE
</code>
logging.info('Exporting the certificate from the cert store...')
transient_password = 'transient'
command = f'''$env:PSModulePath = [Environment]::GetEnvironmentVariable('PSModulePath', 'Machine');
$secret = ConvertTo-SecureString -String {transient_password} -Force -AsPlainText;
Export-PfxCertificate -Cert (Get-ChildItem -Path {CERT_PATH}) -FilePath caccpprod.pfx -Password $secret
'''
child = subprocess.run(['powershell', '-command', command], capture_output = True)
if (child.returncode != 0):
logging.error(f'Encountered an error exporting the Windows Store cert to a PFX: {child.stderr.decode("UTF-8")}')
return False, False
with open('caccpprod.pfx', 'rb') as pfx_file:
private_key, serial, chain = pkcs12.load_key_and_certificates(
pfx_file.read(),
transient_password.encode(),
default_backend()
)
with open(CER_FILE, 'wb') as cer_file:
cer_file.write(serial.public_bytes(serialization.Encoding.PEM))
with open(KEY_FILE, 'wb') as key_file:
key_file.write(private_key.private_bytes(
encoding = serialization.Encoding.PEM,
format = serialization.PrivateFormat.PKCS8,
encryption_algorithm = serialization.NoEncryption()
))
logging.info('Exported the certificate into .cer and .key files')
return CER_FILE, KEY_FILE