# Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file LICENSE.rst or https://cmake.org/licensing for details. # Run this script on a Windows host in a CMake single-config build tree. param ( [string]$signtool = 'signtool', [string]$cpack = 'bin\cpack', [string]$pass = $null ) $ErrorActionPreference = 'Stop' # Cleanup temporary file(s) on exit. $null = Register-EngineEvent PowerShell.Exiting -Action { if ($certFile) { Remove-Item $certFile -Force } } # If the passphrase was not provided on the command-line, # check for a GitLab CI variable in the environment. if (-not $pass) { $pass = $env:SIGNTOOL_PASS # If the environment variable looks like a GitLab CI file-type variable, # replace it with the content of the file. if ($pass -and $pass.EndsWith("SIGNTOOL_PASS") -and (Test-Path -Path "$pass" -IsValid) -and (Test-Path -Path "$pass" -PathType Leaf)) { $pass = Get-Content -Path "$pass" } } # Collect signtool arguments to specify a certificate. $cert = @() # Select a signing certificate to pass to signtool. if ($certX509 = Get-ChildItem -Recurse -Path "Cert:" -CodeSigningCert | Where-Object { $_.PublicKey.Oid.FriendlyName -eq "RSA" } | Select-Object -First 1) { # Identify the private key provider name and container name. if ($certRSA = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($certX509)) { # $certRSA -is [System.Security.Cryptography.RSACng] # Cryptography Next Generation (CNG) implementation $csp = $certRSA.Key.Provider $kc = $certRSA.Key.KeyName } elseif ($certRSA = $certX509.PrivateKey) { # $certRSA -is [System.Security.Cryptography.RSACryptoServiceProvider] $csp = $certRSA.CspKeyContainerInfo.ProviderName $kc = $certRSA.CspKeyContainerInfo.KeyContainerName } # Pass the selected certificate to signtool. $certFile = New-TemporaryFile $certBase64 = [System.Convert]::ToBase64String($certX509.RawData, [System.Base64FormattingOptions]::InsertLineBreaks) $certPEM = "-----BEGIN CERTIFICATE-----", $certBase64, "-----END CERTIFICATE-----" -join "`n" $certPEM | Out-File -FilePath "$certFile" -Encoding Ascii $cert += "-f","$certFile" # Tell signtool how to find the certificate's private key. if ($csp) { $cert += "-csp","$csp" } if ($kc) { if ($pass) { # The provider offers a syntax to encode the token passphrase in the key container name. # https://web.archive.org/web/20250315200813/https://stackoverflow.com/questions/17927895/automate-extended-validation-ev-code-signing-with-safenet-etoken $cert += "-kc","[{{$pass}}]=$kc" $pass = $null } else { $cert += "-kc","$kc" } } } else { $cert += @("-a") } # Sign binaries with SHA-1 for Windows 7 and below. & $signtool sign -v $cert -t http://timestamp.digicert.com -fd sha1 bin\*.exe if (-not $?) { Exit $LastExitCode } # Sign binaries with SHA-256 for Windows 8 and above. & $signtool sign -v $cert -tr http://timestamp.digicert.com -fd sha256 -td sha256 -as bin\*.exe if (-not $?) { Exit $LastExitCode } # Create packages. & $cpack -G "ZIP;WIX" if (-not $?) { Exit $LastExitCode } # Sign installer with SHA-256. & $signtool sign -v $cert -tr http://timestamp.digicert.com -fd sha256 -td sha256 -d "CMake Windows Installer" cmake-*-win*.msi if (-not $?) { Exit $LastExitCode }