I'm trying to use SignTool.exe to code sign an executable with a certificate installed into the Windows certificate store. I'm able to get it to work by installing the cert into the Local Machine/Personal section and then running as an administrator, but I can't seem to work out the right place where the certificate needs to be installed to run as the current user.
I've installed the cert into Current User/Personal and when I do:
Get-ChildItem -Path Cert:\CurrentUser\My
the certificate is in the list. But when I try sign with:
& "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin\signtool.exe"
sign /v /n "West Wind Technologies"
/s MY
/tr "http://timestamp.digicert.com" /td SHA256 /fd SHA256
".\Builds\CurrentRelease\MarkdownMonsterSetup.exe"
running as a non-admin user it doesn't work. I get:
SignTool Error: No certificates were found that met all the given criteria.
If I add the /sm flag and run run as an administrator and have it in the personal store - it works.
Where do I have to put the certificate in the cert store to get it to run without administrator rights?
For the current user you can use Certmgr to import it to the Personal folder.
I use the signtool /n option.
A bit more difficult is when you use signtool in a automated environment as (if your security is setup correctly) the build agent is running under limited service account. An option could be to use a file then.
Related
I'm trying to sign an executable using Microsoft's signtool.exe
The private key lives in an HSM and can not be taken out. So, i had to get the "public" part of the certificate in a .cer file and used below command to sign
signtool.exe sign /v /f .\SigningCert.pem /csp "HSM Key Storage Provider" /k "KEYID" /tr http://timestamp.digicert.com /fd sha256 /td sha256 .\App.exe
Since the machine i used for signing did not have the intermediate certificate added to Windows trust store, the signed executable could not be verified.
SignTool Error: WinVerifyTrust returned error: 0x800B010A
A certificate chain could not be built to a trusted root authority.
That being said, I used below command to add the intermediate certificate using /ac switch
signtool.exe sign /v /f .\SigningCert.pem /csp "HSM Key Storage Provider" /k "KEYID" /ac .\Intermediate.pem /tr http://timestamp.digicert.com /fd sha256 /td sha256 .\App.exe
The executable could be verified properly. So far so good.
Now, if my certificate chain has more than one intermediate certs, how could i add them to signatures?
Example chain:
Leaf Cert -> Intermediate 1 -> Intermediate 2 -> Root Cert
I tried merging all the intermediate certs into a single pem file and using it with /ac switch. Apparently, Signtool takes only the first certificate from the pem file and ignores the rest.
Also, If i want to add cross certificates from Microsoft apart from my intermediate certificates, how would i add them?
As far as i read, I can put all the certs into a pfx file and use it with signtool. But, as i mentioned, i don't have access to the private key. I do not think building a pfx file is an option for me.
I'm setting up a new development laptop, and have installed a self-issued code signing certificate. I can see it in certmgr under my Current Users's Personal Certificates.
When I try to build from the Developer Command Prompt For Visual Studio 2017 I get:
error : SignTool Error: No certificates were found that met all the given criteria.
This always worked fine on my old laptop.
I have found if I run the same build from the command prompt after starting it as admin that signtool succeeds and can find the cert.
This has happened to 3/4 colleagues when we've set up new laptops. One guy is ok and can sign without running as admin. On our old laptops we never had to run as admin.
I've tried googling to find what could be the cause because I wasn't aware that running as admin or not should have any affect over this. I haven't found any reference to this problem.
How can we use signtool.exe without running it as admin?
When not running as admin it appears to be at the Private Key filter step where the cert I'm expecting to be selected gets filtered out:
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.9.12
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
C:\>signtool sign /v /debug /ph /i "<issuedby>" /fd sha256 /td sha256 "C:\TestSign.dll"
The following certificates were considered:
Issued to: Scott Langham
Issued by: <issuedby>
Expires: Sun Sep 25 09:54:55 2022
SHA1 hash: <a_hash>
Issued to: Scott Langham
Issued by: <issuedby_somethingelse>
Expires: Wed May 13 15:51:14 2020
SHA1 hash: <b_hash>
After EKU filter, 1 certs were left.
After expiry filter, 1 certs were left.
After Issuer Name filter, 1 certs were left.
After Private Key filter, 0 certs were left.
SignTool Error: No certificates were found that met all the given criteria.
I've ensured the version of signtool.exe I'm using is the same as the one that my colleague who has this working is using (10.0.18362.1). I've been able to spot any other differences between our systems.
I ran into this today and here is how I am now able to run signtool.exe via command line without elevating to admin.
Run 'mmc' and add the 'Certificates' snap-in
Select the correct key store location
(mine is in Local Computer so I select 'Computer account' here)
Find and select the certificate
Right click on the certificate, select All Tasks > Manage Private Keys...
In the 'Permissions for private keys' dialog, Add your user account and then give yourself 'Full Control'. You will now be able to sign using a normal command prompt.
Note: If you use a build machine, do the above steps for the account that performs the builds.
Similar to what #Baget said, I'd compare the certificates on your machine to that of your colleague who can successfully run the SignTool.exe command without the elevation token. Here's a chunk of PowerShell to assist you:
get-childitem -Path Cert:\ | foreach-object ({
$location = $_.Location
foreach($store in $_.StoreNames.Keys) {
get-childitem -Path "Cert:\$location\$store" | foreach-object ({
$thumb = $($_.ThumbPrint)
$issuer = $($_.Issuer)
if ($issuer -eq "CN=EXAMPLE, DC=EXAMPLE, DC=EXAMPLE, DC=EXAMPLE") {
write-host "$location $store $issuer"
}
})
}
})
Bear in mind that the output of the above may differ slightly if you run as a normal user and 'run as admin'.
Finally, do you and your colleague have the same UAC settings?
I found myself in a similar situation with signtool, it refused to work with an admin user but does work as actual Administrator.
In my case, I am not actually importing the certificate into the certificate store, but using a .pkcs12 file exported from a comodo certificate in firefox, so this makes things even stranger, as no permissions on any keys in the store are involved.
I tried granting myself permissions on some server key, but that did nothing.
I hope someone finds a solution to this problem.
In the meantime, I am signing my exe with osslsigncode instead, which works perfectly.
I extracted the exe and dependent dlls from the msys2 mingw64 build, here is a zip of everything in case it is of use to anyone, just extract it to a directory and put it in your PATH.
http://cachemiss.com/files/osslsigncode.zip
To extract this program yourself from an msys2 installation, you can use this command:
pacman --noconfirm -S mingw-w64-x86_64-osslsigncode
cd /mingw64/bin
mkdir ~/osslsigncode
cp osslsigncode.exe $(ldd osslsigncode.exe | sed -n 's,^.*\(/mingw64/[^ ]*\).*,\1,p' | sort -u) ~/osslsigncode/
cd
zip -9r osslsigncode.zip osslsigncode
I am using this in Visual Studio cmake builds with no issue.
There are two Certificate Store in Windows, User Store, and a machine store, you probably installed the certificate to the local machine, or you installed it when you run as elevated user.
Firstly you are getting such an error and you are using visual studio then See the signing tab in project properties. You will see a previously assigned signature (strong assembly)
If you enter the correct password here:
If your environment is the same as the environment in which the project is written, you will skip this error. Look the post on about the error
The reasons behind this error are:
1- Visual Studio needs some features when using certificate file to sign strong assembly.
ClickOnce Manifest Signing and Strong-Name Assembly Signing Using Visual Studio Project Designer's Signing Page
You can try this code to determine
signtool sign /debug /f mypfxfile.pfx /p <password> (mydllexectuable).exe
2- These settings can vary from machine to machine, and windows does not write these settings to the environment setting by default. check the config path
This part is just a deep note! not interested with the question you should add your private keystore file to request header and those all for this. My favorite steps about the creation of a certificate on this post
I have a .NET application I am trying to sign with a Comodo cert. I am using the following to sign my program.
"C:\Program Files (x86)\kSign\signtool.exe" sign /f "E:\repos\NGS Code Signing Cert 2015.pfx" /p XXXXXX /fd sha1 /t http://timestamp.comodoca.com /d "test program" /du "http://www.mywebsitesoftware.com" "E:\repos\i2x.net\MSI Setups\i2xInstaller\bin\Release\test.exe"
"C:\Program Files (x86)\Windows Kits\10\bin\x64\signtool.exe" sign /f "E:\repos\NGS Code Signing Cert 2015.pfx" /p XXXXXX /fd sha256 /tr http://timestamp.comodoca.com/?td=sha256 /td sha256 /d "test program" /du "http://www.mywebsitesoftware.com" "E:\repos\i2x.net\MSI Setups\i2xInstaller\bin\Release\test.exe"
This works fine and dual signs the EXE. This can be verified by check the program properties and you can see the digital signatures. The problem is that Windows 7 x64 shows the digital signatures but when running as admin shows 'Unknown publisher' (I have tested this on 3 different machines that are fully up to date)
It DOES works fine in Windows Server 2008, 2012, 2016 and Windows 8.1 and 10.
Has anyone else seen this before?
Thanks
The problem was incomplete Windows updates of my both test VM's and on my bosses test machine. Once the machines where FULLY updated (and that took 6 or 7 times of forcing Windows to update and it did not matter if the Microsoft KB3033929 that included the SHA256 support was installed) the things started working.
My goal is to sign an unsigned executable file on Windows using a certificate. From my general knowledge I know that I need a public and a private key pair for a digital signature. I have also installed the Windows SDK, which provides signtool.exe and makecert.exe.
I have already obtained a certificate online, comprising a CER, a PEM, and a CRT file.
My question now is how I have to use these tools and the certificate files in order to sign an executable. According to here, the CRT file is the private key. From what I've learned so far, the CER and the PEM file are basically the same but with different encodings. What are the they for? Are they the public key? And how do I sign my executable?
EDIT: I've tried installing the CRT file to a certificate store and then signing using that certificate:
"C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe" sign /debug /fd SHA256 /a /n "<Issued_To>" /t http://timestamp.comodoca.com/authenticode <Filename>
Here <Issued_To> was replaced with the data from the certificate and <Filename> is the name of the file I wanted to sign. The output I get from signtool is the following:
The following certificates were considered:
...
Issued to: ...
Issued by: Certum Code Signing CA SHA2
Expires: Thu Oct 12 14:37:04 2017
SHA1 hash: BA081A67D3F2DDDC9268121DCBA04F43D6CD37FB
...
After EKU filter, 1 certs were left.
After expiry filter, 1 certs were left.
After Subject Name filter, 1 certs were left.
After Private Key filter, 0 certs were left.
SignTool Error: No certificates were found that met all the given criteria.
For what it's worth, I purchased Certum Cloud Signing for open source projects and here is how I got it working. (It took me 5 business days of mails, trying and error and using google translate on polish documents, so maybe I save a little time to someone)
You first provide your personal information, Once you receive the activation token, you only have 24 hours to activate it. (even if this info is not specified, dont let time pass as I did), so:
Use the "Secret for regaining access to the SimplySign service" in the link that looks like: https://cloudsign.webnotarius.pl/arc/app/resetseed?token=...
There you will get a new code that you should use on the SimplySign mobile app (Reset button, I believe).
I wasnt able to find SimplySign mobile app on google play. So I used a desktop browser to find the App (which said "This app is not compatible with your device", and/or country...) and downloaded the APK using a chrome extension, then installed manually on my phone.
Once you have the mobile app setup, it should be generating 6 digit tokens every minute or so.
Now install SimplySign Desktop on Windows. Log in using your email and the 6 digits token from your mobile. Once it says "Status: Connected" it has installed a virtual smartcard and your certificate. SimplySign must stay connected for the certificate to work.
signtool.exe sign /n "Open Source Developer, Your Name" /fd SHA256 YourApp.exe
If you don't use /fd SHA256 you will get:
SignTool Error: SignedCode::Sign returned error: 0x80090027
The parameter is incorrect.
SignTool Error: An error occurred while attempting to sign: YourApp.exe
If you don't login into SimplySign, you get:
After EKU filter, 1 certs were left.
After expiry filter, 1 certs were left.
After Subject Name filter, 1 certs were left.
After Private Key filter, 0 certs were left.
SignTool Error: No certificates were found that met all the given criteria.
Note: There is no need to install proCertum SmartSign app.
This solved my question: http://www.anse.de/programming/code-signing-for-open-source-executable
I exported the certificate as a PK2 file using Firefox. Then I installed this certificate in the "Personal" certificate store on Windows. Afterwards I could use the aforementioned command to sign my executable:
signtool sign /fd SHA256 /a /n "<Issued_To>" /t http://timestamp.comodoca.com/authenticode <Filename>
Here <Issued_To> matches the value in the certificate and <Filename> is the name of the file to be signed. Afterwards the executable file is signed.
I am an individual, not a company and i am working on a virtual kernel mode device driver. I am aware that I can test sign a driver and run in test mode. However I want to distribute my driver free of cost , but i don't have the resources to buy signature through verisign or globalsign as it is very costly and i am not earning anything through this driver .
Also test signing a driver will be a daunting task for some of the user . So i want to know is there any workaround to use the driver without signature in 64bit ?. Like run it in compatibility for 32bit , or a script that can self sign the driver on behalf of the user.
So now the question essentially is , if i distribute all the exes mentioned in this procedure and make a script to run all these
commands . Then can the driver be signed by the user using the
script?
PROCEDURE :
1.execute Inf2Cat.exe /driver:"U:\MyDriver" /os:7_X64
2.Find makecert.exe in WDK Makecert -r -pe -ss PrivateCertStore -n "CN=TestCertforWDK" TestCert.cer
3.Use Signtool.exe in WDK to sign the cat file Signtool sign /v /s PrivateCertStore /n TestCertForWDK /t
http://timestamp.verisign.com/scripts/timestamp.dll
"U:\MyDriver\MyDriver.cat"
4.Use Signtool.exe in WDK to sign the driver Signtool sign /v /s PrivateCertStore /n TestCertForWDK /t
http://timestamp.verisign.com/scripts/timestamp.dll
"U:\MyDriver\MyDriver.sys"
5.On test computer, import the certificate: certmgr.exe /add TestCert.cer /s /r localMachine root
6.Add it to trusted publisher list certmgr.exe /add TestCert.cer /s /r localMachine trustedpublisher
7.Verify the sign for driver Signtool verify /pa /v MyDriver.sys
8.Verify the sign for cat file Signtool verify /pa /v /c MyDriver.cat MyDriver.inf
So the answer to this question is a big fat no. I'm sorry, but unless you find a user driven workaround, or some company willing to sponsor (sign your driver) it is impossible (i mean improbable :) ). This feature has been implemented in windows to prevent the installation of them pesky rootkits.
Although it probably seems harsh, it prevents a lot of rootkits from being able to install on user machines. In fact, Microsoft recently patched a flaw related to driver signing that was allowing hackers to use microsoft's signing engine within windows to sign drivers that would be accepted by the system.
I highly doubt that you find a way to get around this programmatically. And if you do, let me know.
Getting the driver signed is the only proper way to get your driver on user machines and run it without hassles. You cannot expect the user to put the machine in test signing mode. I think you can refer to test signing costs to have an idea how it costs and I recommend you try to invest in that considering your driver long term. Not sure if there has been any changes in rates.
https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/9a839ac3-4438-43bb-b1b8-4ed8da58ab45/how-much-does-it-cost-to-get-hck-certificates?forum=whck