I'm trying to automate the process of generating a certificate signing request and then importing the response from the CA on a Windows Server 2012 R2 server to use as a cert for a SSL binding in IIS. I'm able to generate the CSR which I then provide to the security team which then provides me with a response to then import but am having troubles getting it to import.
This server is in a workgroup. Thought I'd mention that so no AD enrollment policy.
Here's my process:
Generate a CSR with certreq.exe on the server in question. An INF file is generated that looks something like this:
[Version]
Signature = "$Windows NT$"
[NewRequest]
Subject = "C=US,S=California,L=City,O=Company,OU=IT,CN=hostname"
Exportable = TRUE
KeyLength = 2048
KeySpec = 1
KeyUsage = 0xa0
MachineKeySet = True
ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
ProviderType = 12
Silent = True
SMIME = False
RequestType = PKCS10
This INF file then gets turned into the CSR .req file by doing this:
certreq.exe -new "C:\inffile.inf" "C:\certreq.req"
The REQ file gets sent to the security team and they give me back a .CER file, which, when imported manually, actually adds three certificates from Digicert. The certificate I expect and what looks to be some intermediate CAs.
Here's what that looks like when imported via the MMC Certificates snapin.
If I import the certificate via the MMC like this it doesn't show up in the IIS manager under Server Certificates so I looked a little deeper. I tried to complete the certificate signing request via the the IIS manager like this and the cert shows up and I'm happy.
However, I can't use the GUI since I'm using a script.
I confirm that the request is in Certificate Enrollment Requests with the private key.
I confirm that the public key of the CSR and the p7b I got back provided are the same.
certutil -dump issuedcert.cer
certutil -dump certreq.req
PROBLEM: I exported the CSR from Certificate Enrollment Requests and looked at the public key. It was NOT the same as the one in issuedcert.cer. It looks like this is the problem but why?
I then try to use certreq.exe to accept the response and it doesn't work.
certreq.exe -accept -machine "C:\issuedcert.cer"
Almost done, but no. I continually receive this error message:
This error indicates that certreq was unable to find related request object in the Certificate Enrollment Requests node in the certificate store.
In addition, I would suggest to check whether the public key in the certificate request match the one in the issued certificate. You can use certutil -dump file.req command to dump request file (there will be public key) and cerutil -dump cert.cer to dump issued certificate and compare public keys. Do the same for each object in the Certificate Enrollment Requests node in the certificate store (focused on Local Machine context) to find request object with matching public key.
here is the function i've used in the past:
function AddCertificate(
[string] $MachineName,
[string] $CertString, #String to search for in the Certificate Store to get the correct Thumbprint
[string] $SiteName, #Sitename to bind the certificate to.
[string] $certname, #File name of the certificate
[string] $certPass, #Password for the certificate
[string] $certPath) #path on the machine where this script runs that contains the certificate path needs to not have a Trailing \
{
$Protocol = "https"
$destinationFolder = "c$\temp\pfx-files"
$servers = $MachineName
$session = New-PsSession –ComputerName $servers
$servers | foreach-Object{if(!(Test-Path -path ("\\$_\"+$destinationFolder))) {New-Item ("\\$_\"+$destinationFolder) -Type Directory}}
$servers | foreach-Object{copy-item -force -Path c:\temp\pfx-files\*.* -Destination ("\\$_\"+$destinationFolder)}
$certPath ="c:\temp\pfx-files" +"\"+$certname
Invoke-command -Session $session -ScriptBlock {param($certPass,$certPath) certutil -p $certPass -importpfx ($certPath )}
$servers | foreach-object {Remove-Item -Path (("\\$_\"+$destinationFolder) +"\*.pfx")}
Invoke-Command -session $session {Import-Module WebAdministration}
$isBound = Invoke-Command -session $session {Get-WebBinding }
if (!(Select-String -Pattern "https" -InputObject $isbound -quiet))
{
Invoke-command -Session $session -ScriptBlock {param([string] $S, [string] $Protocol)( New-WebBinding -Name $S -Protocol $Protocol -Port 443 -IPAddress "*" -SslFlags 0)} -ArgumentList $SiteName, $Protocol
Invoke-Command -session $session -ScriptBlock { param([string]$Certstring) $CertShop=Get-ChildItem -Path Cert:\LocalMachine\My | where-Object {$_.subject -like $CertString } | Select-Object -ExpandProperty Thumbprint}
Invoke-Command -Session $session -ScriptBlock {get-item -Path "cert:\localmachine\my\$certShop" | new-item -path IIS:\SslBindings\0.0.0.0!443}
}
Exit-PSSession
}
Adam, try to rename your .cer to .p7b and try certreq -accept file.p7b.
Certreq seems look for the file extension to determine the file type. It supports p7b file for -accept according to the MS docs.
The problem might be that DigiCert Root CA is not trusted in your windows 2012 system. Try to import it manually into the Trusted Root Authorities in LocalMachine store.
Then I would check if there is still a request in Certificate Enrollment Requests in LocalMachine store using MMC.
If there is then it should work fine to just import the given certificate to LocalMachine/My store (in MMC the name is Personal)
If there is not a request there then import certificate in LocalMachine/My store. Then run certutil -store my in cmd. It will go through all certificates in LocalMachine/My, display information about them and try to do encryption test. I assume that all encryption tests will fail. The important thing is to get index of your certificate (certificates begin with index 0). Find the number of the certificate and then use command
certutil -repairstore -csp "Microsoft RSA SChannel Cryptographic Provider" {index of the certificate}
This will try to repair the connection between certificate and private key. When you run certutil -store my again you should see encryption test passed.
Related
I need to automate creating a keyvault and adding two certificates to the vault. I have one self-signed without a password and one wildcard cert signed from a valid authority.
When I try and import them the signed cert gets added fine but the self-signed returns an error...
Import-AzureKeyVaultCertificate : Pending Certificate not found: cluster-app-primary
At script.ps1:18 char:1
Import-AzureKeyVaultCertificate -VaultName $name -Name 'cluster-app...
+ CategoryInfo : CloseError: (:) [Import-AzureKeyVaultCertificate], KeyVaultErrorException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.KeyVault.ImportAzureKeyVaultCertificate
The powershell code is as follows:
Import-AzureKeyVaultCertificate -VaultName $name -Name 'cluster-app-primary' -FilePath "..\..\Certificates\cluster-app-primary.pfx"
Now the exact same command with the other certificate works fine (with a password though).
Also note that if I try and import the self-signed certificate through the Azure portal it works fine.
Does anyone know what this error means and is there anything I can do to import this thru powershell?
Thanks.
I think this issue related to your self-signed cert, the command works fine on my side. Try to create a pfx certificate with a password like below, becasue when you import the certificate in the portal, it also asks for a password.
$certroopath = "C:\Users\Administrator\Desktop"
$certname = "mycert1"
$certpassword = "P#ssw0rd1234"
$cert = New-SelfSignedCertificate -DnsName "$certname" -CertStoreLocation cert:\CurrentUser\My
$pwd = ConvertTo-SecureString -String $certpassword -Force -AsPlainText
$certwithThumb = "cert:\CurrentUser\my\"+$cert.Thumbprint
$filepath = "$certroopath\$certname.pfx"
Export-PfxCertificate -cert $certwithThumb -FilePath $filepath -Password $pwd
Then import it to azure keyvault, it works fine.
$mypwd = ConvertTo-SecureString -String "P#ssw0rd1234" -Force -AsPlainText
Import-AzKeyVaultCertificate -VaultName joykeyvault -Name testc1 -FilePath C:\Users\Administrator\Desktop\mycert1.pfx -Password $mypwd
UPDATE
I could not get this to work so what I did was use the CertificateString parameter instead. I just took the string of the exact same certificate and it worked fine and imported it.
Import-AzKeyVaultCertificate -VaultName $name -Name $certName -CertificateString "MII..."
With the following command I am able to generate self-signed certificate at PowerShell prompt:
$mycert = New-SelfSignedCertificate -DnsName "myhost.westeurope.cloudapp.azure.com" -CertStoreLocation "cert:\LocalMachine\My"
Then I can export it to a PFX file:
$mypwd = ConvertTo-SecureString -String "1234" -Force –AsPlainText
Export-PfxCertificate -FilePath .\mycert.pfx -Password $mypwd -Cert $mycert
Finally, I can import the certificate into Azure Keyvault:
$kvcert = Import-AzKeyVaultCertificate -VaultName mykeyvault -Name mycert -FilePath .\mycert.pfx -Password $mypwd
The above commands work well for me and I can call Import-AzKeyVaultCertificate repeatedly without any errors. Which is important for me, because I want to call the command from an Azure pipeline as a build for pull requests in our team.
My question is -
I don't want to commit the PFX file into our Git repo.
Instead I want to inline the base64 content of it in a PowerShell script, just to have 1 less file in the repo and not having to figure out URL and SAS token for the pipeline.
I am able to base64 format the PFX file content with the follwoing commands at the PowerShell:
$Bytes = [System.IO.File]::ReadAllBytes("c:\tmp\mycert.pfx");
$Base64 = [System.Convert]::ToBase64String($Bytes);
And now I could copy-paste it into my PowerShell script with $Base64 = "D3AB.....ICB9A==";
But how to pass it to the Import-AzKeyVaultCertificate command in my script?
Is there some trick like echo $Base64 | Import-AzKeyVaultCertificate -FilePath - like in Linux for STDIN?
I'm following How to add a certificate to an Azure RM website with Powershell and trying to add a certificate with the following Powershell
New-AzureRmWebAppSSLBinding -ResourceGroupName MyResource -WebAppName mysite -Name www.contoso.com -CertificateFilePath "C:\Secure\mycert.pfx" -CertificatePassword plaintextPassword
But it's returning with
New-AzureRmWebAppSSLBinding : The specified network password is not correct.
However, if I use the Azure portal I can add the certificate successfully from the pfx file, so the password is definitely correct.
New-AzureRmWebAppSSLBinding : The specified network password is not correct.
As far as I know, the certificate will be added via REST when we execute New-AzureRmWebAppSSLBinding cmdlet. And I could see this request details if I specify -Debug parameter for New-AzureRmWebAppSSLBinding cmdlet.
And if I provide an incorrect value for -CertificatePassword, It returns the same error.
So please check the CertificatePassword again to make sure you provide the same value (the value of Certificate password input on Azure portal) for New-AzureRmWebAppSSLBinding cmdlet.
I know this is dated. However for anyone else that runs into the issue try the following.
-CertificatePassword "PlainTextPassword"
Don't forget to add the quotes.
To take it a step further, for the sake of security, you can pass in your certificate password via keyvault.
$vaultname = "keyvault"
$secrectname = "keyvaultsecret"
$resourcegroup = "resourcegroupname"
$webappname = "webappname"
$hostname = "example.com"
$secretsecurestring = Get-AzureKeyVaultSecret -
VaultName $vaultname -Name $secretname
$pfxpass = $secretsecurestring.SecretValueText
New-AzureRmWebAppSSLBinding -ResourceGroupName
$resourcegroup -WebAppName $webappname -
CertificateFilePath C:\Certificate.pfx -
CertificatePassword $pfxpass -Name $hostname
If I create an Azure Linux VM using PowerShell, how can I get its new ssh host key, so that I can install it in my local ssh/putty? Preferably the solution is also PowerShell code.
Old question, but for newcomers there is nowadays an alternative available by using run-command in Azure CLI. There is probably an equivalent for PowerShell too, but I have not investigated that.
az vm run-command invoke --name <your-vm-name> --command-id RunShellScript --scripts "cat /etc/ssh/ssh_host_ecdsa_key.pub"
will output a json document from which you can extract the public key. Beware though that this process is incredibly slow (~30 seconds per host), but you only need to run it once. See this gist for an example of how to update the known_hosts file with Ansible.
You can use a new "Run Command" feature of Azure Portal.
In your Virtual Machine page, go to "Run command" in "Operations" section of VM menu.
Select "RunShellScript" command.
Paste the following command:
for f in /etc/ssh/ssh_host_*_key; do ssh-keygen -l -f "$f"; done
You will get an output like:
Enable succeeded:
[stdout]
256 SHA256:bKKCom8yh5gOuBNWaHHJ3rrnRXmCOAyPN/WximYEPAU /etc/ssh/ssh_host_ecdsa_key.pub (ECDSA)
256 SHA256:IYeDl+gseYk46Acg4g2mcXGvCr7Z8FqOd+pCJz/KLHg /etc/ssh/ssh_host_ed25519_key.pub (ED25519)
2048 SHA256:rA0lIXvHqFq7VHKQCqHwjsj28kw+tO0g/X4KnPpEjMk root#myazurevm (RSA)
[stderr]
(the set of key types will vary with your VM image)
The feature can also be used via Azure CLI, what is shown in the link above and also in the answer by #mwik.
Check also my complete guide to Connecting securely to Microsoft Azure service with SFTP.
The RSA, DSA, ECDSA, and ED25519 keys are generated on first boot, and available in the boot diagnostics log.
If you don't catch it on the first boot, I don't think it's listed anywhere else in the portal. There's only one feasible, secure option of which I can think for recovering the fingerprint for an already-deployed VM.
Create a new VM.
Attach the VHD of the VM for which you need the fingerprint.
Verify your connection to the new VM using the fingerprint in the boot diagnostics.
Check the fingerprint for the generated /etc/ssh/ssh_host_rsa_key.pub file on the other disk.
ssh-keygen -lf /{path}/ssh_host_rsa_key.pub
You may need to add the -E md5 switch if you need the hexadecimal encoded MD5 hash.
PowerShell
To get the boot diagnostics data via PowerShell:
Get-AzureRmVMBootDiagnosticsData -ResourceGroupName ExampleGroup -Name TestLab -Linux
Connecting with Putty
Azure computes the host key fingerprints as a Base64 encoded string of the SHA-256 hash of the public key. When you attempt to connect using Putty, it presents the fingerprint as a hexadecimal encoded string of the MD5 hash of the public key.
Fortunately, Azure also lists the full public key in the boot diagnostics log, where it says BEGIN SSH HOST KEY KEYS in the second image. With that, we can manually compute the fingerprint as presented by Putty.
C#
static string ComputeMD5FingerprintFromBase64(string encoded)
{
// Convert Base64 string to byte array.
byte[] pub = Convert.FromBase64String(encoded);
// Compute MD5 hash.
HashAlgorithm md5 = MD5.Create();
byte[] hash = md5.ComputeHash(pub);
return BitConverter.ToString(hash).Replace('-', ':');
}
Windows
For instructions on securely connecting to a Windows VM with RDP, see my answer on this StackOverflow question.
Perhaps this is exactly what you're looking for. I will try it with you on my account right now.
Basically it looks like you need to attach a .pem upon creation.
Which should yield your certificate thumbprint.
Windows VM Example
Select-AzureSubscription mysub
$service = 'yourservicename1'
$location = 'West US'
New-AzureService -ServiceName $service -Location $location
Add-AzureCertificate -CertToDeploy 'D:User-DatadevelopmentAzure Samplesmlwdevcert.cer' -ServiceName $service
$cert1 = New-AzureCertificateSetting -Thumbprint D7BECD4D63EBAF86023BB4F1A5FBF5C2C924902A -StoreName 'My'
New-AzureVMConfig -ImageName 'MSFT__Windows-Server-2012-Datacenter-201208.01-en.us-30GB.vhd' -InstanceSize 'Small' -Name 'win2012cert' |
Add-AzureProvisioningConfig -Windows -Password 'somepass#1' -Certificates $cert1 | New-AzureVM -ServiceName $service
Linux VM Example
Select-AzureSubscription mysub
$service = 'yourservicename1'
$location = 'West US'
New-AzureService -ServiceName $service -Location $location
Add-AzureCertificate -CertToDeploy 'D:User-DatadevelopmentAzure Samplesmlwdevcert.cer' -ServiceName $service
$sshkey = New-AzureSSHKey -PublicKey -Fingerprint D7BECD4D63EBAF86023BB4F1A5FBF5C2C924902A -Path '/home/admin/.ssh/authorized_keys'
New-AzureVMConfig -ImageName 'CANONICAL__Canonical-Ubuntu-12-04-amd64-server-20120528.1.3-en-us-30GB.vhd' -InstanceSize 'Small' -Name 'linuxwithcert' |
Add-AzureProvisioningConfig -Linux -LinuxUser 'mwasham' -Password 'somepass#1' -SSHPublicKeys $sshKey |
New-AzureVM -ServiceName $service
Note: The -Certificates and -SSHPublicKeys parameters are arrays so they can accept multiple certificates.
-SSHPublicKeys $sshKey1,$sshKey2
For Linux there is also the -SSHKeyPairs parameter for passing a key pair instead of just the public key. -Certificates can handle both types on Windows.
In their help document, there is a page talking about how to reset the password or ssh key:
https://learn.microsoft.com/en-us/azure/virtual-machines/linux/troubleshoot-ssh-connection
How do I create a self-signed certificate for code signing using tools from the Windows SDK?
Updated Answer
If you are using the following Windows versions or later: Windows Server 2012, Windows Server 2012 R2, or Windows 8.1 then MakeCert is now deprecated, and Microsoft recommends using the PowerShell Cmdlet New-SelfSignedCertificate.
If you're using an older version such as Windows 7, you'll need to stick with MakeCert or another solution. Some people suggest the Public Key Infrastructure Powershell (PSPKI) Module.
Original Answer
While you can create a self-signed code-signing certificate (SPC - Software Publisher Certificate) in one go, I prefer to do the following:
Creating a self-signed certificate authority (CA)
makecert -r -pe -n "CN=My CA" -ss CA -sr CurrentUser ^
-a sha256 -cy authority -sky signature -sv MyCA.pvk MyCA.cer
(^ = allow batch command-line to wrap line)
This creates a self-signed (-r) certificate, with an exportable private key (-pe). It's named "My CA", and should be put in the CA store for the current user. We're using the SHA-256 algorithm. The key is meant for signing (-sky).
The private key should be stored in the MyCA.pvk file, and the certificate in the MyCA.cer file.
Importing the CA certificate
Because there's no point in having a CA certificate if you don't trust it, you'll need to import it into the Windows certificate store. You can use the Certificates MMC snapin, but from the command line:
certutil -user -addstore Root MyCA.cer
Creating a code-signing certificate (SPC)
makecert -pe -n "CN=My SPC" -a sha256 -cy end ^
-sky signature ^
-ic MyCA.cer -iv MyCA.pvk ^
-sv MySPC.pvk MySPC.cer
It is pretty much the same as above, but we're providing an issuer key and certificate (the -ic and -iv switches).
We'll also want to convert the certificate and key into a PFX file:
pvk2pfx -pvk MySPC.pvk -spc MySPC.cer -pfx MySPC.pfx
If you are using a password please use the below
pvk2pfx -pvk MySPC.pvk -spc MySPC.cer -pfx MySPC.pfx -po fess
If you want to protect the PFX file, add the -po switch, otherwise PVK2PFX creates a PFX file with no passphrase.
Using the certificate for signing code
signtool sign /v /f MySPC.pfx ^
/t http://timestamp.url MyExecutable.exe
(See why timestamps may matter)
If you import the PFX file into the certificate store (you can use PVKIMPRT or the MMC snapin), you can sign code as follows:
signtool sign /v /n "Me" /s SPC ^
/t http://timestamp.url MyExecutable.exe
Some possible timestamp URLs for signtool /t are:
http://timestamp.verisign.com/scripts/timstamp.dll
http://timestamp.globalsign.com/scripts/timstamp.dll
http://timestamp.comodoca.com/authenticode
http://timestamp.digicert.com
Full Microsoft documentation
signtool
makecert
pvk2pfx
Downloads
For those who are not .NET developers, you will need a copy of the Windows SDK and .NET framework. A current link is available here: [SDK & .NET][5] (which installs makecert in `C:\Program Files\Microsoft SDKs\Windows\v7.1`). Your mileage may vary.
MakeCert is available from the Visual Studio Command Prompt. Visual Studio 2015 does have it, and it can be launched from the Start Menu in Windows 7 under "Developer Command Prompt for VS 2015" or "VS2015 x64 Native Tools Command Prompt" (probably all of them in the same folder).
As stated in the answer, in order to use a non deprecated way to sign your own script, one should use New-SelfSignedCertificate.
Generate the key:
New-SelfSignedCertificate -DnsName email#yourdomain.com -Type CodeSigning -CertStoreLocation cert:\CurrentUser\My
Export the certificate without the private key:
Export-Certificate -Cert (Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert)[0] -FilePath code_signing.crt
The [0] will make this work for cases when you have more than one certificate... Obviously make the index match the certificate you want to use... or use a way to filtrate (by thumprint or issuer).
Import it as Trusted Publisher
Import-Certificate -FilePath .\code_signing.crt -Cert Cert:\CurrentUser\TrustedPublisher
Import it as a Root certificate authority.
Import-Certificate -FilePath .\code_signing.crt -Cert Cert:\CurrentUser\Root
Sign the script (assuming here it's named script.ps1, fix the path accordingly).
Set-AuthenticodeSignature .\script.ps1 -Certificate (Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert)
Obviously once you have setup the key, you can simply sign any other scripts with it.
You can get more detailed information and some troubleshooting help in this article.
It's fairly easy using the New-SelfSignedCertificate command in Powershell.
Open powershell and run these 3 commands.
Create certificate:
$cert = New-SelfSignedCertificate -DnsName www.yourwebsite.com -Type CodeSigning -CertStoreLocation Cert:\CurrentUser\My
Set the password for it:
$CertPassword = ConvertTo-SecureString -String "my_passowrd" -Force -AsPlainText
Export it:
Export-PfxCertificate -Cert "cert:\CurrentUser\My\$($cert.Thumbprint)" -FilePath "d:\selfsigncert.pfx" -Password $CertPassword
Your certificate selfsigncert.pfx will be located # D:/
Optional step: You would also require to add certificate password to system environment variables. do so by entering below in cmd:
setx CSC_KEY_PASSWORD "my_password"
Roger's answer was very helpful.
I had a little trouble using it, though, and kept getting the red "Windows can't verify the publisher of this driver software" error dialog. The key was to install the test root certificate with
certutil -addstore Root Demo_CA.cer
which Roger's answer didn't quite cover.
Here is a batch file that worked for me (with my .inf file, not included).
It shows how to do it all from start to finish, with no GUI tools at all
(except for a few password prompts).
REM Demo of signing a printer driver with a self-signed test certificate.
REM Run as administrator (else devcon won't be able to try installing the driver)
REM Use a single 'x' as the password for all certificates for simplicity.
PATH %PATH%;"c:\Program Files\Microsoft SDKs\Windows\v7.1\Bin";"c:\Program Files\Microsoft SDKs\Windows\v7.0\Bin";c:\WinDDK\7600.16385.1\bin\selfsign;c:\WinDDK\7600.16385.1\Tools\devcon\amd64
makecert -r -pe -n "CN=Demo_CA" -ss CA -sr CurrentUser ^
-a sha256 -cy authority -sky signature ^
-sv Demo_CA.pvk Demo_CA.cer
makecert -pe -n "CN=Demo_SPC" -a sha256 -cy end ^
-sky signature ^
-ic Demo_CA.cer -iv Demo_CA.pvk ^
-sv Demo_SPC.pvk Demo_SPC.cer
pvk2pfx -pvk Demo_SPC.pvk -spc Demo_SPC.cer ^
-pfx Demo_SPC.pfx ^
-po x
inf2cat /drv:driver /os:XP_X86,Vista_X64,Vista_X86,7_X64,7_X86 /v
signtool sign /d "description" /du "www.yoyodyne.com" ^
/f Demo_SPC.pfx ^
/p x ^
/v driver\demoprinter.cat
certutil -addstore Root Demo_CA.cer
rem Needs administrator. If this command works, the driver is properly signed.
devcon install driver\demoprinter.inf LPTENUM\Yoyodyne_IndustriesDemoPrinter_F84F
rem Now uninstall the test driver and certificate.
devcon remove driver\demoprinter.inf LPTENUM\Yoyodyne_IndustriesDemoPrinter_F84F
certutil -delstore Root Demo_CA
As of PowerShell 4.0 (Windows 8.1/Server 2012 R2) it is possible to make a certificate in Windows without makecert.exe.
The commands you need are New-SelfSignedCertificate and Export-PfxCertificate.
Instructions are in Creating Self Signed Certificates with PowerShell.
You can generate one in Visual Studio 2019, in the project properties. In the Driver Signing section, the Test Certificate field has a drop-down. Generating a test certificate is one of the options. The certificate will be in a file with the 'cer' extension typically in the same output directory as your executable or driver.
This post will only answer the "how to sign an EXE file if you have the crtificate" part:
To sign the exe file, I used MS "signtool.exe". For this you will need to download the bloated MS Windows SDK which has a whooping 1GB. FORTUNATELY, you don't have to install it. Just open the ISO and extract "Windows SDK Signing Tools-x86_en-us.msi". It has a merely 400 KB.
Then I built this tiny script file:
prompt $
echo off
cls
copy "my.exe" "my.bak.exe"
"c:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x64\signtool.exe" sign /fd SHA256 /f MyCertificate.pfx /p MyPassword My.exe
pause
Details
__