How to check the certificate used to sign QDT binary¶
Tip
Starting with the 0.39.0 version, the released binary for Windows is signed with a self-signed certificate linked to Oslandia as subject. See how it’s done behind the scenes for a full transparency report.
Certificate materials¶
Since we use a self-signed certificate, we publish the material used to show QDT’s worth:
the Certificate Signing Request (CSR): builder/code_signing_certificate_request.csr which ships:
identity (DN : CN, O, etc)
the public key extracted from the private key used to sign the certificate
the Certificate itself (CRT): builder/code_signing_certificate.crt which ships:
identity (DN : CN, O, etc)
the public key extracted from the private key used to sign the certificate
extensions (ELU, validity dates…)
digital sign
Windows¶
Extract certificate information from the binary¶
Run this command in a PowerShell terminal:
Get-AuthenticodeSignature .\dist\qdt.exe | Format-List *
That should return the following:
SignerCertificate : [Subject]
E="qgis+qdt@oslandia.com", CN=oslandia.com, O=Oslandia, L=Paris, S=Ãle-de-France, C=FR
[Issuer]
E="qgis+qdt@oslandia.com", CN=oslandia.com, O=Oslandia, L=Paris, S=Ãle-de-France, C=FR
[Serial Number]
5A3010F0288B365E02251F02C25CBEF2E52199F1
[Not Before]
22/09/2025 18:38:28
[Not After]
20/09/2035 18:38:28
[Thumbprint]
8D4D002E279490E07D0782CF62824A524D142968
TimeStamperCertificate : [Subject]
CN=DigiCert SHA256 RSA4096 Timestamp Responder 2025 1, O="DigiCert, Inc.", C=US
[Issuer]
CN=DigiCert Trusted G4 TimeStamping RSA4096 SHA256 2025 CA1, O="DigiCert, Inc.", C=US
[Serial Number]
0A80EF184B8DF10582D1C476A7957468
[Not Before]
04/06/2025 02:00:00
[Not After]
04/09/2036 01:59:59
[Thumbprint]
DD6230AC860A2D306BDA38B16879523007FB417E
Status : UnknownError
StatusMessage : Une chaîne de certificats a été traitée mais s’est terminée par un certificat racine qui n’est pas approuvé
par le fournisseur d’approbation
Path : C:\Users\username\Downloads\dist\Windows_QGISDeploymentToolbelt_0-39-0.exe
SignatureType : Authenticode
IsOSBinary : False
Import the certificate in your local store¶
Download the CRT file from official QDT repository
Right-clic on the downloaded file and select “Install certificate…” to launch the Certificate Import Wizard.
Choose the certificate scope: Active directory, Local Machine or current user. Depending on your choice, it may require administrator privileges. Then click Next.
Select Place all certificates in the following store, then click Browse…
Choose the certificate store
Trusted Publishers
:Click OK, then Next.
Click Finish to complete the import.
A security warning may appear for self-signed certificates; confirm by clicking Yes to trust the certificate.
Check it in certificate management console¶
In your start menu, search for “certificat” and click on “Manage user certificates” to open the Certificate Manager (certmgr).
Expand
Certificates
, then expand the folder corresponding to the store you imported into (e.g.,Trusted Publishers
>Certificates
).
Automate import with a PowerShell script¶
<#
.Synopsis
Download the certificate use to sign the QDT executable and import it to the local store.
.DESCRIPTION
This script downloads a CRT certificate file from a GitHub repository, imports it into a specified certificate store on the local machine,
and sets a friendly name and description for the certificate.
.PARAMETER storeName
The name of the Windows certificate store where the certificate will be imported. Default: "TrustedPublisher"
.PARAMETER storeScope
The scope of the certificate store. Can be "CurrentUser" or "LocalMachine". Default: "CurrentUser".
.PARAMETER friendlyName
The friendly name to assign to the certificate in the Windows certificate store.
.PARAMETER description
The description to assign to the certificate (stored as a certificate property).
.EXAMPLE
.\import_cert.ps1 -storeName Root -storeScope LocalMachine
.NOTES
Requires to be run as administrator to import into machine-level stores.
.LICENSE
SPDX-License-Identifier: Apache-2.0
#>
# -- VARIABLES
param(
[string]$storeName = "TrustedPublisher", # Default store is Trusted Publishers
[string]$storeScope = "CurrentUser", # default scope is CurrentUser; use "LocalMachine" for machine-wide store (requires admin rights)
[string]$friendlyName = "QDT Code Signing Certificate",
[string]$description = "Certificate issued by Oslandia for signing QDT executables. See online documentation: https://qgis-deployment.github.io/qgis-deployment-toolbelt-cli/."
)
# remote CRT URL
$certUrl = "https://raw.githubusercontent.com/qgis-deployment/qgis-deployment-toolbelt-cli/refs/heads/main/builder/code_signing_certificate.crt"
# local path where storing the downloaded certificate
$localCertPath = "$env:TEMP\qdt_code_signing_certificate.crt"
# -- MAIN
# validate store scope
if ($storeScope -notin @("CurrentUser","LocalMachine")) {
Write-Error "Invalid store scope. Use 'CurrentUser' or 'LocalMachine'."
exit 1
}
# if LocalMachine scope is requested, ensure the script is running with admin rights
if ($storeScope -eq "LocalMachine") {
$currentUser = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
if (-not $currentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)) {
Write-Warning "This script requires administrator privileges for LocalMachine scope. Relaunching with elevation..."
Start-Process -FilePath "powershell" -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`" $args" -Verb RunAs
exit
}
}
Invoke-WebRequest -Uri $certUrl -OutFile $localCertPath
Write-Host "Certificate downloaded to $localCertPath"
# Load the certificate
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($localCertPath)
# Add metadata to improve integration with Windows certificate manager
$cert.FriendlyName = "QDT Code Signing Certificate"
$cert.Extensions.Add(
New-Object System.Security.Cryptography.X509Certificates.X509Extension("2.5.29.17", [System.Text.Encoding]::ASCII.GetBytes($description), $false)
)
# Open the specified certificate store (LocalMachine)
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store($storeName, $storeScope)
$store.Open("ReadWrite")
# Import the certificate
$store.Add($cert)
$store.Close()
Write-Host "Certificate imported into $storeName store with scope $storeScope and Friendly Name: '$friendlyName'"