What password does domain-protected pfx require? - powershell

I try to create a self-signed code signing certificate via powershell to sign a .NET assembly through Visual Studio 2017 with it as a pfx afterwards. The pfx is exported as a domain-protected certificate using -ProtectTo argument. The code is as follows:
$pfxLocation = [System.IO.Path]::Combine([System.Environment]::GetFolderPath("Desktop"),"Certificates\")
New-Item -ItemType Directory -Path $pfxLocation -Force
$certificate = New-SelfSignedCertificate `
-CertStoreLocation "Cert:\LocalMachine" `
-FriendlyName "This is a code-signing certificate" `
-Subject "CN=Me" `
-Type CodeSigningCert `
-NotBefore ([System.DateTime]::Today) `
-NotAfter ([System.DateTime]::Today.AddMonths(6).AddDays(1)) `
-KeyExportPolicy Exportable
Move-Item -Destination "Cert:\LocalMachine\Root" -Path $certificate.PSPath
$newCertificateLocation = "Cert:\LocalMachine\Root\" + $certificate.Thumbprint
Get-ChildItem $newCertificateLocation | Export-PfxCertificate -FilePath ([System.IO.Path]::Combine($pfxLocation,"certificate.pfx")) -ProtectTo "Domain\Domain group 1", "Domain\Domain group 2"
However, Visual Studio still demands a non-existent password.
Password from domain user from one of domain groups specified with -ProtectTo argument is rejected:
So what password does it request and why does it require any at all? As it's domain-protected, it shouldn't have any, and that's exactly what I was aiming at.
UPDATE
Basically, the idea is to use output pfx for code signing with automated build agents, for which absence of password is kind of a must.

This export PFX without password. When importing this through GUI, you can use empty password.
$cert = #(Get-ChildItem -Path 'Cert:\CurrentUser\My\07BAE0886EECC2019F0AE6CC68FE5C3EA98308F8')[0]
$certBytes = $cert.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Pfx)
[System.IO.File]::WriteAllBytes('S:\cert.pfx', $certBytes)

Does this work for you?
& certutil -v -privatekey certificate.pfx | ? {$_ -match "^PFX protected password: ""(?<password>.*)""$"} | % { $matches.password }

Related

Signing Assemblies using Certificate Thumprint using Powershell

What I want to achieve: I would like to sign my files using an existing Certificate Thumbprint.
I have an existing yml file that contains the following bit of code that is executed in a github workflow:
- name: Import signing cert
shell: pwsh
id: import_cert
run: |
$pfx = [System.Convert]::FromBase64String("${{ secrets.SIGNING_CERT }}")
$certPath = '.\CompanyCertificate.pfx'
[IO.File]::WriteAllBytes($certPath, $pfx)
$certPass = ConvertTo-SecureString '${{ secrets.SIGNING_CERT_PASSWORD }}' -AsPlainText -Force
Import-PfxCertificate -FilePath $certPath -CertStoreLocation Cert:\CurrentUser\My -Password $certPass
$thumbprint = (Get-PfxCertificate -FilePath $certPath -Password $certPass).Thumbprint
echo "::set-output name=THUMB_PRINT::$thumbprint"
I then loop through all the assemblies that need signing and try sign the assemblies(dlls and exes):
Write-Host "Signing assemblies"
$filesToSign = Get-ChildItem -Path "${{ github.workspace }}\folder\Programs" -Include *.dll,*.exe -Recurse |
Get-AuthenticodeSignature |
Where-Object status -eq 'NotSigned'
Set-AuthenticodeSignature -FilePath $filesToSign.path -Certificate '${{ steps.import_cert.outputs.THUMB_PRINT }}'
But I am getting the following error:
Cannot bind parameter 'Certificate'. Cannot convert value <"Certificate Thumbprint Redacted"> to type "System.Security.Cryptography.X509Certificates.X509Certificate2". Error: "The system cannot find the file specified."
Now I assume this is because I am trying to make use of the thumbprint from the certificate, which is gotten from my Import signing cert step, but this is existing code, so I dont want to change this.
My question: Can I sign my files using the Certificates Thumbprint ?
Thanks!
I found the solution. I needed to search for the Certificate based on the Thumbprint and then pass it through to the Set-AuthenticodeSignature:
$cert = Get-ChildItem -path 'Cert:\*${{ steps.import_cert.outputs.THUMB_PRINT }}' -Recurse
Set-AuthenticodeSignature -FilePath $filesToSign.path -Certificate $cert

Create a certificate file in PKCS#8 format with DER encoding

I need to create a certificate file, that should be in PKCS#8 format with DER encoding. I will use this certificate for encrypting/decrypting the SAML Assertions in AD B2C.
I have tried using the OpenSSL commands, but unable to achieve it.
Can someone please provide any steps or references to create the certificate file? I am using windows environment.
For B2C IEF Policy keys, you can export a certificate file as .pfx and upload the same on the portal.
You can check the doc here for the details:https://learn.microsoft.com/en-us/azure/active-directory-b2c/connect-with-saml-service-providers#11-prepare-a-self-signed-certificate
Also you can use PowerShell to create and export the .pfx:
New-SelfSignedCertificate `
-KeyExportPolicy Exportable `
-Subject "CN=yourappname.yourtenant.onmicrosoft.com" `
-KeyAlgorithm RSA `
-KeyLength 2048 `
-KeyUsage DigitalSignature `
-NotAfter (Get-Date).AddMonths(12) `
-CertStoreLocation "Cert:\CurrentUser\My"
$pwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText
$thumbprint = (Get-ChildItem -Path cert:\CurrentUser\My\ | Where-Object{$_.Subject -eq "CN=yourappname.yourtenant.onmicrosoft.com"}).Thumbprint
$cert = "cert:\CurrentUser\My\$thumbprint"
Get-ChildItem -Path cert:\CurrentUser\My\$thumbprint | Export-PfxCertificate -FilePath C:\temp\B2CCert.pfx -Password $pwd
I already tried this in the lab and this PowerShell script would help you in exporting the newly created Self-Signed Certificate in .pfx format in the location "C:\temp\B2CCert.pfx".
You can just use the .pfx format certificate that got created above.
Do let us know if this works.

Export-PfxCertificate : Cannot export non-exportable private key

I am attempting to export my self-signed certificate so I can import it to other Servers in my development environment (will use "real" certs for Production), but it throws the following error:
Export-PfxCertificate : Cannot export non-exportable private key
The requirements are that I need to export the cert and "allow the private key to be exported", but am curious what I am missing. My PowerShell is as follows:
$pwd = ConvertTo-SecureString -String ‘1234’ -Force -AsPlainText
$path = 'cert:\localMachine\my\' + '1E7439053EE57AEE6EA0E1F3CDF5DB4234B6731E'
Export-PfxCertificate -cert $path -FilePath c:\Certificates\cert.pfx -Password $pwd
The problem isn't with the powershell code. The problem is with the certificate.
When a certificate is first imported or created, the private key must be marked as exportable in order for you to be able to export the private key.
The error message you have received indicates that the private key is not exportable on the certificate you are trying to use.
Example Issue
Maybe too late, but have you tried to run PowerShell script as administrator? (If you can export private key from mmc console, Export-PfxCertificate will export it also.)
I know this is an older question, but I wanted to post my solution as I was having this same problem.
I too was getting the dreaded Export-PfxCertificate : Cannot export non-exportable private key error while trying to export my PFX file.
The problem started after loading my code-signing certificate on my Windows machine.
When I went to export it, the export to PFX option was grayed out without further explanation. I then followed many of the instructions listed here, including Powershell Export-PfxCertificate. None of these worked.
I finally went back to my Certificate provider GoDaddy and they informed me that in my Original Certificate Signing Request (CSR) I did not check the box Make Private Key Exportable.
GoDaddy graciously, and without cost, allowed me to submit a new CSR (with that option checked,) to 'Rekey' my existing certificate. Within a couple of hours, my new certificate was issued. I installed it on my machine and was able to export directly from Windows MMC (no need to PowerShell.)
I've included this screenshot of the box that must be checked when creating your CSR (may look different on different platforms.)
I did a quick search, and you can use certutil or better is probably the solution from http://community.idera.com/powershell/powertips/b/tips/posts/exporting-certificate-with-private-key.
Relevant code from that post has been pasted below. 100% attribution to the author of that page.
dir cert:\currentuser\my |
Where-Object { $_.hasPrivateKey } |
Foreach-Object { [system.IO.file]::WriteAllBytes(
"$home\$($_.thumbprint).pfx",
($_.Export('PFX', 'secret')) ) }
Use Import-PfxCertificate with parameter -Exportable
Get-ChildItem -Path c:\mypfx\my.pfx | Import-PfxCertificate -CertStoreLocation Cert:\CurrentUser\My -Exportable
check my Code below.
#Ask for the Name
$name = Read-Host "Certificate Name "
# Check if the Path exists
$Path = "D:\Provisioning\certmgmt\$name.txt"
$TestPath = Test-Path $Path
if ($TestPath -ne "true")
{
Write-Host "The Path $Path do not exist" -ForegroundColor Red
Pause
exit
}
# Import the certificate
$result = Import-Certificate -FilePath $Path -CertStoreLocation "Cert:\LocalMachine\My"
# Get the serialnumber of the certificate
$Thumbprint = $result.Thumbprint
# Set the FriendlyName
(Get-ChildItem -Path Cert:\LocalMachine\My\$Thumbprint).FriendlyName = $name
# Export the Certificate
$answer = Read-Host "Export Certificate? (Y/N)"
if ($answer -eq "N" -or $answer -eq "n")
{
exit
}
try
{
$mypwd = ConvertTo-SecureString -String "password" -Force -AsPlainText
Get-ChildItem -Path cert:\localMachine\my\$Thumbprint | Export-PfxCertificate -FilePath C:\$name.pfx -Password $mypwd
}
catch
{
Write-Host $Error -ForegroundColor Red
pause
exit
}
Write-Host "Export the Certifikate was successful" -ForegroundColor Green

Get ssl certificates thumbprint from directory in powershell

I have an application that is throwing an exception because the ssl certificate is not installed on my machine. I know the tumbprint of the missing certificate but I do not know how to find it by name.
I have done this:
Get-ChildItem -Path Cert:\LocalMachine\My
And verified that the cert i need is not installed. I have the certs in my source code directory(c:\source\project\certs) but I need to know which cert in the directory to install.
Is there a way to list the certs like in the line above but from the "c:\source\project\certs" folder instead of the cert store?
This should do the trick:
$password= ConvertTo-SecureString -String "Pass" -AsPlainText -Force
Get-ChildItem -Path "C:\source\project\certs" -Filter *.pfx | % {
$certobject = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$certobject.import($_.FullName, $password, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::DefaultKeySet)
$certobject.Thumbprint
}

Does powershell has a tool to create not-selfsigned certificate?

Theres a tool in powershell called New-SelfSignedCertificate that we can create selfsigned certificates for CA proposes.
But i just cant figure out if its possible to create child certificates issued/signed by that certificate created before by this New-SelfSignedCertificate. Actually i can do that with makecert.exe, but i would like to script it in powershell.
For example, in makecert.exe, i execute these commands:
1)Creating the CA cert: **makecert.exe** -sk RootCA -sky signature -pe -n CN=ca.com -r -sr LocalMachine -ss Root RootCA
2)Creating another cert for server signed by above CA: **makecert.exe** -sk server -sky exchange -pe -n CN=server.com -ir LocalMachine -is Root -ic RootCA -sr LocalMachine -ss My server.com
In powershell i just know to create a CA, using that command:
New-SelfSignedCertificate -DnsName "ca.com" -CertStoreLocation cert:Localmachine/My
But, how to create another cert signed by that one above?
Other thing, when I try to put the -CertStoreLocation = cert:Localmachine/**Root** i get an error message saying that i can only create a certificate in MY store (i already executing as administrator)
Thanks.
I am so sorry to be late to the party, I'm well aware it's been two years since this question was asked.
However, to share with those who may find this entry when searching - there is now a way (documented on this excellent blog by David Christiansen)
In summary,
New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "Your root CA name here"
Note down the thumbprint returned from this command.
Next, create a secure password and export the root CA into a file
PowerShell
$pwd = ConvertTo-SecureString -String "Please-Use-A-Really-Strong-Password" -Force -AsPlainText
Export-PfxCertificate -cert cert:\localMachine\my\[CA thumbprint] -FilePath root-authority.pfx -Password $pwd
Export-Certificate -Cert cert:\localMachine\my\[CA thumbprint] -FilePath root-authority.crt
Note that the crt file does not need a password as it is the public component of the certificate.
Now load the signing certificate into memory and create a certificate signed by this cert, exporting it with a password.
$rootcert = ( Get-ChildItem -Path cert:\LocalMachine\My\[CA Thumbprint] )
New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "Your DNS Name Here" -Signer $rootcert
Note down the thumbprint returned from the self-signed cert command to export it.
$pwd2 = ConvertTo-SecureString -String "Please-Use-A-Really-Strong-Password" -Force -AsPlainText
Export-PfxCertificate -cert cert:\localMachine\my\[Cert Thumbprint] -FilePath gateway-certificate.pfx -Password $pwd2
Export-Certificate -Cert cert:\localMachine\my\[Cert Thumbprint] -FilePath gateway.crt
it seems cumbersome to note the hashes of the certificates manually. it's simpler to do it like this:
# create root zertificate
$rootCert = New-SelfSignedCertificate -CertStoreLocation cert:\localmachine\my -DnsName "Root CA Name";
# export root certificate
[System.Security.SecureString]$rootcertPassword = ConvertTo-SecureString -String "znft5yeL34pxCu3nATlt1gMazX0NM8FVvr9yZOhcS79yJm8kUVjhA17UuWkQOb0u" -Force -AsPlainText;
[String]$rootCertPath = Join-Path -Path 'cert:\localMachine\my\' -ChildPath "$($rootcert.Thumbprint)";
Export-PfxCertificate -Cert $rootCertPath -FilePath 'root-authority.pfx' -Password $rootcertPassword; # private key
Export-Certificate -Cert $rootCertPath -FilePath 'root-authority.crt'; # public key
# use root certificate to sign gateway certificate
$gatewayCert = New-SelfSignedCertificate -CertStoreLocation cert:\localmachine\my -DnsName "*.example.com","*.example.org" -Signer $rootCert;
# export gateway certificate
[System.Security.SecureString]$gatewayCertPassword = ConvertTo-SecureString -String "Xc8FlsHq8hmLnKXk4AaD8ug6HYH2dpSWLjwg9eNeDIK103d3akbd0OccgZZ6bL48" -Force -AsPlainText;
[String]$gatewayCertPath = Join-Path -Path 'cert:\localMachine\my\' -ChildPath "$($gatewayCert.Thumbprint)";
Export-PfxCertificate -Cert $gatewayCertPath -FilePath gateway-certificate.pfx -Password $gatewayCertPassword; # private key
Export-Certificate -Cert $gatewayCertPath -FilePath gateway.crt; # public key
Also, for an prodution environment, you probably want to use ACMESharp to create free TLS certificates.