Signing Windows binaries on Server Core Windows Server 2019 Datacenter Edition with Visual Studio 2019 Community.
signtool.exe was not behaving correctly (issues opening PFX file), and so we were advised to switch to PowerShell + Set-AuthenticodeSignature.
Using the following commands:
$securepassword = ConvertTo-SecureString -String $password -AsPlainText -Force
$pfx = Get-PfxData -FilePath $certificate -Password $securepassword
$cert = $pfx.EndEntityCertificates[0]
Set-AuthenticodeSignature -FilePath $target -Certificate $cert -HashAlgorithm "SHA256" -TimestampServer http://timestamp.digicert.com
results in a binary with the expected SHA256 signature, however, the Timestamp Signature is SHA1. Have also tried using http://timestamp.digicert.com?alg=sha256 as the server, however Set-AuthenticodeSignature does not add the timestamp signature at all.
Since this command doesn't allow you to specify the hash of the Timestamp algorithm, how can we achieve this?
Use another RFC3161 timestamp server. For example:
-TimestampServer "http://timestamp.comodoca.com/rfc3161"
I also see this issue in Windows 10 Enterprise when trying to use -TimestampServer "http://timestamp.digicert.com?alg=sha256" in PowerShell, despite this timestamp server working fine with signtool in the same environment.
If one flushes the local DNS cache and then observes the network interface with Wireshark, both signtool and Set-AuthenticodeSignature normally trigger a DNS lookup for the timestamp server during the signing process. This does not occur when using the DigiCert URL with Set-AuthenticodeSignature. The cmdlet seems like it may be having an issue with the ?alg=sha256 parameter and then skips the timestamp step completely.
Related
I have make authorization link using Spring Boot OAuth2.0 but I don't have client secret instead I have to use certificate. Any idea how to solve this?
You can use client assertion instead of a client secret. The client uses a certificate to prove the token request came from the client. You can use a self-signed certificate to create the client assertion
Please check this official document and upload a certificate as below
If the script for the document didn't work, please use the script below to create a self-assigned certificate.
$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
Utilize the ClientID and TenantID that are used while the Powershell script is running. The output from the PowerShell script should be used for the client assertion parameter.
https://login.microsoftonline.com/{TenantID}/oauth2/v2.0/token
For more information in detail, please refer below links:
Using client assertion to get access tokens from Azure AD
https://blogs.aaddevsup.xyz/2020/10/how-to-use-postman-to-perform-a-client-credentials-grant-flow-with-a-certificate/
Owin.dll, the assembly inside the Owin package on Nuget.org, does not have an Authenticode signature. However, on Windows Server 2016 and Windows Server 2019, Get-AuthenticodeSignature (and sigcheck.exe) incorrectly report that Owin.dll does have an Authenticode signature.
If you deploy a Windows Server VM and run this code, it will return different signing and timestamping certificates (I only did this in Azure):
> [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
> Invoke-WebRequest "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -OutFile NuGet.exe
> .\NuGet.exe install owin -o .
> Get-AuthenticodeSignature .\Owin.1.0\lib\net40\Owin.dll | Format-List
On Windows Server 2019, it returns a SignerCertificate with Thumbprint AE9C1AE54763822EEC42474983D8B635116C8452 and TimestamperCertificate Thumbprint 893ED0E4D032C3855D5D2296B2DE2DD1AFB897DD.
On Windows Server 2016, it returns a SignerCertificate with Thumbprint E85459B23C232DB3CB94C7A56D47678F58E8E51E and TimestamperCertificate Thumbprint CFC3E3018EA65666DCE484FC7016EB42D1F108A9.
Other certificate metadata indicates that these are, in fact, certificates from Microsoft.
What's going on here? Why does this specific assembly behave this way in these specific versions of Windows?
Whilst the signature isn't part of the Owin.dll itself, Windows Server has a "Security Catalog" (under %SystemRoot%\System32\CatRoot) which identifies Owin.dll by name/hash. The security catalog is signed by Microsoft, and it's the signing certificate of the security catalog that's being returned by Get-AuthenticodeSignature. In effect it's simply a "detached" Authenticode signature, rather than being embedded in the .dll.
I am hosting two windows containers from a Windows 2019 servers and both are running in https. When my Web URL container tried to make a call to the API container. It didn't work and when I got inside the Web container and run the curl command to my API web site and I received the following error.
(77) schannel: next InitializeSecurityContext failed: SEC_E_UNTRUSTED_ROOT (0x80090325) - The certificate chain was issued by an authority that is not trusted.
I am trying to find out how to import the root certificate to my aspnet:3.0 base image.
This is what I did to get certificates working in my docker container. I import the root certificate as well as the certificate for the application, so take the parts you need.
On your host put the certificates (pfx) into a directory and mount it within the container. I will assume you have mounted them on 'C:\certificates' in the container.
I pass the certificates as environmental variables so the script can pick them up.
Add this script to run when the container starts up:
Import-Module WebAdministration
$webCertificatePath = $ENV:WEB_CERTIFICATE_PATH
$webCertificatePassword = $ENV:WEB_CERTIFICATE_PASSWORD
$rootCertificatePaths = $ENV:ROOT_CERTIFICATE_PATHS
# I don't do anything with this... yet
$intermediateCertificatePaths = $ENV:INTERMEDIATE_CERTIFICATE_PATHS
# Import Root Certificate
# You can stop here if you only want the Root Certificate installed.
Import-Certificate -FilePath $rootCertificatePaths -CertStoreLocation 'Cert:\\LocalMachine\Root'
# Import website certificate
$mypwd = ConvertTo-SecureString -String $webCertificatePassword -Force -AsPlainText
$cert = Import-PfxCertificate -FilePath "$webCertificatePath" -Password $mypwd -CertStoreLocation 'Cert:\LocalMachine\My'
if (-not (Test-Path 'IIS:\SSLBindings\0.0.0.0!443')) {
$cert | New-Item 'IIS:\SSLBindings\0.0.0.0!443'
}
There are many ways to do this, but you get the idea.
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
How to extend the expiry date of windows app certificate? We're side loading the app/ The main obstacle is the certificate expires every year which is a bothersome to renew it through GP cause we already have issues in our environment. We would like to extend it for at least 5 years.
I have managed to find technet articles on how to create a code signing certificate but it didnt work. Visual studio doesnt accept the certificate and gives an error message that it is corrupted or invalid.
https://learn.microsoft.com/en-us/windows/uwp/packaging/create-certificate-package-signing#create-a-self-signed-certificate
https://technet.microsoft.com/itpro/powershell/windows/pki/new-selfsignedcertificate
Is there any way to do it easily?
You could do something like this, the subject must be same as UWP app's Publisher (package.appxmanifest):
New-SelfSignedCertificate -Type Custom -Subject "CN=Something" -TextExtension #("2.5.29.37={critical}{text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}") -KeyUsage DigitalSignature -FriendlyName "Friendly Name" -CertStoreLocation "Cert:\LocalMachine\My" -NotBefore (Get-Date) -NotAfter (Get-Date).AddYears(5)
Now export to .pfx and add the thumbprint to the PackageCertificateThumbprint
The process is described in Microsoft documentation, but it is convoluted. There is no "visual" part as "Visual Studio" would suggest.
To sideload an application, it is sufficient to create a self-signed certificate, which means that you trust yourself. There is no trust from a CA (certification authority) involved.
These steps worked for me. The whole process being in PowerShell run as administrator.
Create the certificate
New-SelfSignedCertificate -Type Custom -Subject "CN=Company Name, O=Company Name Inc., C=CA" -KeyUsage DigitalSignature -FriendlyName "Programming certificate, 50 years" -CertStoreLocation "Cert:\CurrentUser\My" -TextExtension #("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}") -NotBefore (Get-Date) -NotAfter (Get-Date).AddYears(50)
The -Subject item may contain only the CN= part, I believe the other bits are optional. O= seems to refer to the organization and C= the country code.
The -CertStoreLocation and -TextExtension are correct as written (see the documentation). I am not too familiar with what -CertStoreLocation really means, as I was not able to find it later, but that is what Microsoft suggests and remains irrelevant to the process.
The (Get-Date) bits get the current date, and .AddYears(50) would be modified to how many years the certificate should last.
The output will display the thumbprint; copy it.
Export the certificate
Set a password variable (confusingly, the password here is written without quotes).
$password = ConvertTo-SecureString -String CustomPasswordYouWouldChoose -Force -AsPlainText
Export the certificate; paste the thumbprint in the "Cert:\CurrentUser\My..." string and choose a file path (in my case, using the C:\ drive worked fine).
Export-PfxCertificate -cert "Cert:\CurrentUser\My\YOURTHUMBPRINTHERE" -FilePath C:\ProgrammingCertificate.pfx -Password $password
Add the certificate in Visual Studio
Go to Package.appxmanifest > Packaging > Choose Certificate... > Select from file... > then select your exported certificate.
Install the certificate on sideload deployment
Double-click the certificate file > Install Certificate... > Local Machine > Place all certificates in the following store > Browse > Trusted People > accept all and the import should be successful. Congratulations, the application is now certified by yourself.