Export-Pfxcertificate command not available in Powershell - powershell

I am trying to create certificate .cer and .pfx files using powershell.
$certroot = "C:\Script\Certificate"
$certname = "TestCertificate15"
$password = read-host "Enter certificate password" -AsSecureString
$startdate = Get-Date
$enddate = $startdate.AddYears(2)
C:\Script\Certificate\makecert.exe -r -pe -n "CN=$certname" -b ($startdate.ToString("MM/dd/yyyy")) -e ($enddate.ToString("MM/dd/yyyy")) -ss my -len 2048
$cert = Get-ChildItem Cert:\CurrentUser\My | ? {$_.Subject -eq "CN=$certname"}
Export-Certificate -Type CERT -FilePath "$certroot\$certname.cer" -Cert $cert -Force
Export-PfxCertificate -FilePath "$certroot\$certname.pfx" -Cert $cert -Password $password -Force
These commands are failing for Export-Certificate and Export-PfxCertificate as commandlets are not supported in the current version.
I have also upgraded the windows powershell framework version to 5.1.
Which specific version of powershell to be used to execute the commands?
Thank you.

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

PowerShell export AD user x509 certificate and import into ADUC for the user

What is the best method in PowerShell for exporting a users AD certificate and storing in a data file.
I can get the users certificate:
$user = Get-ADuser "tester01"
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $user.usercertificate
I want to export this to a file so that I can import it later to a users AD account using PowerShell.
How do I do this?
The PKI issued user certs is on their computer. Just use the certificate drive to get them. Get-PSDrive, Get-ChildItem -Path Cert:. See the help file and the help file examples.
Or use...
Export-Certificate
Module: PKIClient
Exports a certificate from a certificate store into a file.
# Get specifics for a module, cmdlet, or function
(Get-Command -Name Export-Certificate).Parameters
(Get-Command -Name Export-Certificate).Parameters.Keys
Get-help -Name Export-Certificate -Examples
# Results
<#
$cert = (Get-ChildItem -Path
Export-Certificate -Cert $cert -FilePath c:\certs\user.sst -Type SST
$cert = (Get-ChildItem -Path
Export-Certificate -Cert $cert -FilePath c:\certs\user.cer
$cert = ( Get-ChildItem -Path
Export-Certificate -Cert $cert -FilePath c:\certs\user.p7b -Type p7b
Get-ChildItem -Path cert:\CurrentUser\my | Export-Certificate ûFilePath
#>
Get-help -Name Export-Certificate -Full
Get-help -Name Export-Certificate -Online
See also:
https://www.powershellgallery.com/packages/CPolydorou.ActiveDirectory/1.7.0/Content/UserCertificates.psm1

How to create and install X.509 self signed certificates in Windows 10 without user interaction?

The problem
Create and install temporary certificates to sign
code in my development environment.
This has to be done with an unattended
script (without user interaction).
The legacy script
Right now, I have this script that creates the certificates using the deprecated tool makecert:
makecert -r -pe -n "CN=My CA" -ss CA -sr CurrentUser -a sha256 -cy authority -sky signature -sv MyCA.pvk MyCA.cer
certutil -user -addstore Root MyCA.cer
certutil -addstore Root MyCA.cer
makecert -pe -n "CN=My Company" -a sha256 -cy end -sky signature -ic MyCA.cer -iv MyCA.pvk -sv MySPC.pvk MySPC.cer
pvk2pfx.exe -pvk MySPC.pvk -spc MySPC.cer -pfx MySPC.pfx
certutil -f -user -p "" -importPFX MySPC.pfx
The above script creates 2 certificates:
MyCA.cer: A self-signed root authority certificate.
MySPC.cer: The cerificate to sign my code (signed with MyCA.cer).
This script also opens dialog boxes requesting a user password and user confirmation to install the certificate in the Trusted Root Certification Authorities Store. I need this to be done without user interaction.
The new script
Following this instructions, I rewrited the legacy script with powershell cmdlet New-SelfSignedCertificate. This is what I tried:
# Create a self-signed root authority certificate.
$rootCert = New-SelfSignedCertificate -KeyExportPolicy Exportable -CertStoreLocation cert:\CurrentUser\My -DnsName "Development Root CA" -NotAfter (Get-Date).AddYears(5) -KeyusageProperty All -KeyUsage CertSign,CRLSign,DigitalSignature
# Export the root authority private key.
[System.Security.SecureString] $password = ConvertTo-SecureString -String "passwordx" -Force -AsPlainText
[String] $rootCertPath = Join-Path -Path cert:\CurrentUser\My\ -ChildPath "$($rootcert.Thumbprint)"
Export-PfxCertificate -Cert $rootCertPath -FilePath "MyCA.pfx" -Password $password
Export-Certificate -Cert $rootCertPath -FilePath "MyCA.crt"
# Create a "MySPC" certificate signed by our root authority.
$cert = New-SelfSignedCertificate -CertStoreLocation Cert:\LocalMachine\My -DnsName "MySPC" -TextExtension #("2.5.29.19={text}false") -KeyLength 2048 -Signer $rootCert -Type CodeSigningCert -KeyUsage None
# Save the signed certificate with private key into a PFX file and just the public key into a CRT file.
[String] $certPath = Join-Path -Path cert:\LocalMachine\My\ -ChildPath "$($cert.Thumbprint)"
Export-PfxCertificate -Cert $certPath -FilePath MySPC.pfx -Password $password
Export-Certificate -Cert $certPath -FilePath "MySPC.crt"
# Add MyCA certificate to the Trusted Root Certification Authorities.
$pfx = new-object System.Security.Cryptography.X509Certificates.X509Certificate2
$pfx.import("MyCA.pfx", $password, "Exportable,PersistKeySet")
$store = new-object System.Security.Cryptography.X509Certificates.X509Store(
[System.Security.Cryptography.X509Certificates.StoreName]::Root,
"localmachine"
)
$store.open("MaxAllowed")
$store.add($pfx)
$store.close()
# Import certificate.
Import-PfxCertificate -FilePath MySPC.pfx cert:\CurrentUser\My -Password $password
The new script creates and install MyCA.cer and MySPC.cer without user interaction but these certificates are not the same than the previous ones. For example, When I look at MyCA.cer, the intended purposes are:
Proves your identity to a remote computer
Ensures the identity of a remote computer
All issuance policies
Rather than the expected:
All issuance policies
All application policies
Other problems
With makecert the certificate is created with the Basic Constraint:
Subject Type=CA, but I cannot create such constraint using
New-SelfSignedCertificate.
Finally, the MySPC.cer is unable to sign my code, it fails with an
error like "not valid for the selected purpose".
The Question
How can I generate the same certificates than the legacy script but in unattended way?
Thanks in advance.
EDIT
With changes proposed by Mötz, I'm able to sign but the error is raised in the validation. These are the commands:
Sign command
signtool.exe sign /v /a c:\git\...\Win32\det.dll
The following certificate was selected:
Issued to: XXXXXXXXXX
Issued by: My CA
Expires: Fri Dec 20 20:18:26 2019
SHA1 hash: 0440F2B76E5BBF1F9CB4D24EF5E5AA54F4F4C2E1
Done Adding Additional Store
Successfully signed: c:\git\...\Win32\det.dll
Number of files successfully Signed: 1
Number of warnings: 0
Number of errors: 0
Validation command
signtool.exe verify /pa /v c:\git\...\Win32\det.dll
Signature Index: 0 (Primary Signature)
Hash of file (sha1): E4EC8126CC9510610AF4FC72CC8722B81B171AE1
Signing Certificate Chain:
Issued to: My CA
Issued by: My CA
Expires: Thu Dec 21 01:14:52 2023
SHA1 hash: DA5B1972016D66294886CA3EDA2D4FEF245D7337
Issued to: XXXXXXXXX
Issued by: My CA
Expires: Sat Dec 21 01:24:53 2019
SHA1 hash: 3316486BAF0A53C1C3227F1E522FF776B6F32CC9
File is not timestamped.
SignTool Error: The signing certificate is not valid for the requested usage.
Number of files successfully Verified: 0
Number of warnings: 0
Number of errors: 1
The solution
The accepted solution includes all key things to resolve the problem (a huge thanks to Mötz). I'm including my final script with minor changes just to help others.
#
# This script will create and install two certificates:
# 1. `MyCA.cer`: A self-signed root authority certificate.
# 2. `MySPC.cer`: The cerificate to sign code in
# a development environment (signed with `MyCA.cer`).
#
# No user interaction is needed (unattended).
# Powershell 4.0 or higher is required.
#
# Define the expiration date for certificates.
$notAfter = (Get-Date).AddYears(10)
# Create a self-signed root Certificate Authority (CA).
$rootCert = New-SelfSignedCertificate -KeyExportPolicy Exportable -CertStoreLocation Cert:\CurrentUser\My -DnsName "My CA" -NotAfter $notAfter -TextExtension #("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}CA=1") -KeyusageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature
# Export the CA private key.
[System.Security.SecureString] $password = ConvertTo-SecureString -String "passwordx" -Force -AsPlainText
[String] $rootCertPath = Join-Path -Path cert:\CurrentUser\My\ -ChildPath "$($rootcert.Thumbprint)"
Export-PfxCertificate -Cert $rootCertPath -FilePath "MyCA.pfx" -Password $password
Export-Certificate -Cert $rootCertPath -FilePath "MyCA.crt"
# Create an end certificate signed by our CA.
$cert = New-SelfSignedCertificate -CertStoreLocation Cert:\LocalMachine\My -DnsName "My Company Name" -NotAfter $notAfter -Signer $rootCert -Type CodeSigningCert -TextExtension #("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}CA=0&pathlength=0")
# Save the signed certificate with private key into a PFX file and just the public key into a CRT file.
[String] $certPath = Join-Path -Path cert:\LocalMachine\My\ -ChildPath "$($cert.Thumbprint)"
Export-PfxCertificate -Cert $certPath -FilePath "MySPC.pfx" -Password $password
Export-Certificate -Cert $certPath -FilePath "MySPC.crt"
# Add MyCA certificate to the Trusted Root Certification Authorities.
$pfx = new-object System.Security.Cryptography.X509Certificates.X509Certificate2
$pfx.import("MyCA.pfx", $password, "Exportable,PersistKeySet")
$store = new-object System.Security.Cryptography.X509Certificates.X509Store(
[System.Security.Cryptography.X509Certificates.StoreName]::Root,
"localmachine"
)
$store.open("MaxAllowed")
$store.add($pfx)
$store.close()
# Remove MyCA from CurrentUser to avoid issues when signing with "signtool.exe /a ..."
Remove-Item -Force "cert:\CurrentUser\My\$($rootCert.Thumbprint)"
# Import certificate.
Import-PfxCertificate -FilePath MySPC.pfx cert:\CurrentUser\My -Password $password -Exportable
I just tested your code with the signtool.exe coming from my Visual Studio 2017 installation and things seems to work.
So I would really like to see the code / command you use for signing the files. Even more I would like to see the real output from the error that you are seeing. Could you try your signing process manually / by hand at first, so we are sure that we are focusing on the correct issue?
With that said, I spent some time digging around to answer some of the other questions you had.
Solving the first part of you wanting to only see
All issuance policies
All application policies
This is solved with the TextExtension parameter:
-TextExtension #("2.5.29.37={text}1.3.6.1.4.1.311.10.12.1")
Solving the part that you wanted the
Subject Type = CA
This is solved with the TextExtension parameter:
-TextExtension #("2.5.29.19={text}CA=1&pathlength=3")
The path length is used to limit how many levels of children that can use the certificate. Please read more here. The value 3 is just something is used while testing.
We then need to combine those 2 different TextExtensions entries:
-TextExtension #("2.5.29.37={text}1.3.6.1.4.1.311.10.12.1", "2.5.29.19={text}CA=1&pathlength=3")
Which will have us write the updated script like this
$rootCert = New-SelfSignedCertificate -KeyExportPolicy Exportable -CertStoreLocation cert:\CurrentUser\My -DnsName "Development Root CA" -NotAfter (Get-Date).AddYears(5) -TextExtension #("2.5.29.37={text}1.3.6.1.4.1.311.10.12.1", "2.5.29.19={text}CA=1&pathlength=3") -KeyusageProperty All -KeyUsage CertSign,CRLSign,DigitalSignature
# Export the root authority private key.
[System.Security.SecureString] $password = ConvertTo-SecureString -String "passwordx" -Force -AsPlainText
[String] $rootCertPath = Join-Path -Path cert:\CurrentUser\My\ -ChildPath "$($rootcert.Thumbprint)"
Export-PfxCertificate -Cert $rootCertPath -FilePath "MyCA.pfx" -Password $password
Export-Certificate -Cert $rootCertPath -FilePath "MyCA.crt"
# Create a "MySPC" certificate signed by our root authority.
$cert = New-SelfSignedCertificate -CertStoreLocation Cert:\LocalMachine\My -DnsName "MySPC" -Signer $rootCert -Type CodeSigningCert
# Save the signed certificate with private key into a PFX file and just the public key into a CRT file.
[String] $certPath = Join-Path -Path cert:\LocalMachine\My\ -ChildPath "$($cert.Thumbprint)"
Export-PfxCertificate -Cert $certPath -FilePath MySPC.pfx -Password $password
Export-Certificate -Cert $certPath -FilePath "MySPC.crt"
# Add MyCA certificate to the Trusted Root Certification Authorities.
$pfx = new-object System.Security.Cryptography.X509Certificates.X509Certificate2
$pfx.import("MyCA.pfx", $password, "Exportable,PersistKeySet")
$store = new-object System.Security.Cryptography.X509Certificates.X509Store(
[System.Security.Cryptography.X509Certificates.StoreName]::Root,
"localmachine"
)
$store.open("MaxAllowed")
$store.add($pfx)
$store.close()
# Import certificate.
Import-PfxCertificate -FilePath MySPC.pfx cert:\CurrentUser\My -Password $password
But like I stated earlier, your code seems to generate the correct certificates because I was able to use the certificate it generated and sign an .net EXE file with it.
Before signing
Signing
SignTool sign /n "MySPC" 2LCS.exe
After signing
Update based on the new information
You need to specify the /pa switch on your verify command.
https://knowledge.digicert.com/solution/SO21771.html
https://learn.microsoft.com/en-us/windows/desktop/seccrypto/signtool
Question is if you would see the same with the makecert certificates?
Updated with working code
Your focus on the properties of the certificate got me down the wrong road. Based on a discussion from here I learned that we might need to have it created as a Class 3 code signing. I removed the 1.3.6.1.4.1.311.10.12.1 EKU extension and replaced it with 1.3.6.1.5.5.7.3.3. Please see below code example.
$rootCert = New-SelfSignedCertificate -KeyExportPolicy Exportable -CertStoreLocation cert:\CurrentUser\My -DnsName "Development Root CA" -NotAfter (Get-Date).AddYears(5) -TextExtension #("2.5.29.19={text}CA=1&pathlength=3", "2.5.29.37={text}1.3.6.1.5.5.7.3.3") -KeyusageProperty All -KeyUsage CertSign,CRLSign,DigitalSignature #-Type CodeSigningCert
# Export the root authority private key.
[System.Security.SecureString] $password = ConvertTo-SecureString -String "passwordx" -Force -AsPlainText
[String] $rootCertPath = Join-Path -Path cert:\CurrentUser\My\ -ChildPath "$($rootcert.Thumbprint)"
Export-PfxCertificate -Cert $rootCertPath -FilePath "MyCA.pfx" -Password $password
Export-Certificate -Cert $rootCertPath -FilePath "MyCA.crt"
# Create a "MySPC" certificate signed by our root authority.
$cert = New-SelfSignedCertificate -CertStoreLocation Cert:\LocalMachine\My -DnsName "MySPC" -Signer $rootCert -Type CodeSigningCert
# Save the signed certificate with private key into a PFX file and just the public key into a CRT file.
[String] $certPath = Join-Path -Path cert:\LocalMachine\My\ -ChildPath "$($cert.Thumbprint)"
Export-PfxCertificate -Cert $certPath -FilePath MySPC.pfx -Password $password
Export-Certificate -Cert $certPath -FilePath "MySPC.crt"
# Add MyCA certificate to the Trusted Root Certification Authorities.
$pfx = new-object System.Security.Cryptography.X509Certificates.X509Certificate2
$pfx.import("MyCA.pfx", $password, "Exportable,PersistKeySet")
$store = new-object System.Security.Cryptography.X509Certificates.X509Store(
[System.Security.Cryptography.X509Certificates.StoreName]::Root,
"localmachine"
)
$store.open("MaxAllowed")
$store.add($pfx)
$store.close()
# Import certificate.
Import-PfxCertificate -FilePath MySPC.pfx cert:\CurrentUser\My -Password $password
I ran the following signing command:
And after that I ran the verification command:
With that in place I believe that you should have a working solution. Please test it, verify and then extend it to include your timestamp signing as well.
Installation of certificate on cert store do by Certificate Propagation service.
So you can scan(Scan API) Certificate Propagation service and develop like it.
You can use API Monitor.

What password does domain-protected pfx require?

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 }

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.