Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot Export PFX certificate with key marked as exportable. #12081

Closed
wightsci opened this issue Mar 8, 2020 · 5 comments
Closed

Cannot Export PFX certificate with key marked as exportable. #12081

wightsci opened this issue Mar 8, 2020 · 5 comments
Labels
Issue-Question ideally support can be provided via other mechanisms, but sometimes folks do open an issue to get a Resolution-Answered The question is answered.

Comments

@wightsci
Copy link

wightsci commented Mar 8, 2020

Steps to reproduce

The following steps work on Windows PowerShell 5.1. This issue is present on both x86 and x64 versions and can be reproduced on multiple machines.

I can export the certificate successfully using X509 .Net classes in PowerShell 7.

$TestCertificate = New-SelfSignedCertificate -Subject 'TestCertificate' -KeyExportPolicy 'Exportable'
Export-PfxCertificate -Cert $TestCertificate -FilePath .\TestCertificate.pfx -Password (ConvertTo-SecureString 'TestPassword' -AsPlainText -Force)

Expected behavior

Creation of PFX file.

Actual behavior

Export-PfxCertificate: Cannot export non-exportable private key.

Environment data

Name                           Value
----                           -----
PSVersion                      7.0.0
PSEdition                      Core
GitCommitId                    7.0.0
OS                             Microsoft Windows 10.0.18363
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
@wightsci wightsci added the Issue-Question ideally support can be provided via other mechanisms, but sometimes folks do open an issue to get a label Mar 8, 2020
@iSazonov
Copy link
Collaborator

iSazonov commented Mar 9, 2020

/cc @anmenaga for information

@anmenaga
Copy link
Contributor

anmenaga commented Mar 9, 2020

Looks like this is run on a system with an older version of PKI module.
This older version will engage WinCompat feature and each certificate cmdlet in repro steps will be doing PS Remoting Serialization twice.
Looks like X509Certificate2 is losing its PrivateKey when going over Serialization boundary.
Here is a repro in Windows PowerShell 5.1 with WinRM Remoting session:

PS C:\> $PSVersionTable.PSVersion.ToString()
5.1.14393.3471
PS C:\> $s = New-PSSession localhost
PS C:\> # original X509Certificate2 in remote session has PrivateKey
PS C:\> icm $s {(New-SelfSignedCertificate -Subject 'TestCertFromWinPS' -KeyExportPolicy 'Exportable').HasPrivateKey}
True
PS C:\> # deserialized local copy does Not have PrivateKey
PS C:\> $TestCertificate = icm $s {New-SelfSignedCertificate -Subject 'TestCertFromWinPS' -KeyExportPolicy 'Exportable'}
PS C:\> $TestCertificate.HasPrivateKey
False
PS C:\> # attempt to export deserialized local copy of X509Certificate2 will fail
PS C:\> Export-PfxCertificate -Cert $TestCertificate -FilePath .\TestCertificate.pfx -Password (ConvertTo-SecureString 'Test
Password' -AsPlainText -Force)
Export-PfxCertificate : Cannot export non-exportable private key.
At line:1 char:1
+ Export-PfxCertificate -Cert $TestCertificate -FilePath .\TestCertific ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Export-PfxCertificate], Win32Exception
    + FullyQualifiedErrorId : System.ComponentModel.Win32Exception,Microsoft.CertificateServices.Commands.ExportPfxCertifi
   cate

As a workaround in PS 7 the entire operation can be done in WinCompat session:

PS C:\A> $PSVersionTable.PSVersion.ToString()
7.0.0
PS C:\A> Import-Module PKI -UseWindowsPowerShell # this will create WinPSCompatSesion PS Remoting session
WARNING: Module PKI is loaded in Windows PowerShell using WinPSCompatSession remoting session; please note that all input and output of commands from this module will be deserialized objects. If you want to load this module into PowerShell Core please use 'Import-Module -SkipEditionCheck' syntax.
PS C:\A> $s = Get-PSSession -Name WinPSCompatSession
PS C:\A> icm $s {$TestCertificate = New-SelfSignedCertificate -Subject 'TestCertificate' -KeyExportPolicy 'Exportable'}
PS C:\A> $pass = ConvertTo-SecureString 'TestPassword' -AsPlainText -Force
PS C:\A> icm $s {Export-PfxCertificate -Cert $TestCertificate -FilePath .\TestCertificate.pfx -Password $using:pass | Out-Null}

@PaulHigin can you please confirm that this is expected behavior of private keys for de/serialized certificate objects? Thank you.

@PaulHigin
Copy link
Contributor

Yes, looking at the code, PowerShell remoting rehydrates the dotNet certificate object but without the private key.

@JeremyTBradshaw
Copy link

@anmenaga I am wondering if you know of an alternative approach to the workaround using the WinCompat session you provided. That workaround works great, but it is a little painful. I'm hoping we can just get the private key to be kept intact without having to Invoke-Command to another PSSession. Any idea?

@sergshu
Copy link

sergshu commented Feb 4, 2022

If you run task from Azure DevOps change script type to PowerShell (Not PowerShell Core)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Question ideally support can be provided via other mechanisms, but sometimes folks do open an issue to get a Resolution-Answered The question is answered.
Projects
None yet
Development

No branches or pull requests

6 participants