Files
MrTrust/scripts/Sign-MrTrustProject.ps1
MrSphay b58b6358f4
Some checks failed
Build MrTrust / build-windows (push) Has been cancelled
Add MrTrust GUI and Gitea release build
2026-05-15 23:47:10 +02:00

105 lines
3.3 KiB
PowerShell

[CmdletBinding()]
param(
[Parameter(Mandatory)]
[string[]]$Path,
[string]$PfxPath,
[string]$CertificateThumbprint,
[string]$TimestampServer = "http://timestamp.digicert.com",
[switch]$NoTimestamp,
[switch]$AllowUntrustedRoot
)
$ErrorActionPreference = "Stop"
function Resolve-FullPath {
param([Parameter(Mandatory)][string]$Path)
$executionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path)
}
function Get-CodeSigningCertificateFromStore {
param([Parameter(Mandatory)][string]$Thumbprint)
$normalizedThumbprint = $Thumbprint -replace "\s", ""
$certificate = Get-ChildItem "Cert:\CurrentUser\My", "Cert:\LocalMachine\My" |
Where-Object { $_.Thumbprint -eq $normalizedThumbprint } |
Select-Object -First 1
if (-not $certificate) {
throw "No code-signing certificate found with thumbprint $Thumbprint."
}
$certificate
}
if (-not $PfxPath -and -not $CertificateThumbprint) {
throw "Provide either -PfxPath or -CertificateThumbprint."
}
if ($PfxPath -and $CertificateThumbprint) {
throw "Use either -PfxPath or -CertificateThumbprint, not both."
}
if ($PfxPath) {
$resolvedPfxPath = Resolve-FullPath $PfxPath
if (-not (Test-Path -LiteralPath $resolvedPfxPath)) {
throw "PFX file not found: $resolvedPfxPath"
}
$password = Read-Host "Enter PFX password" -AsSecureString
$storageFlags = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable -bor
[System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet
$certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($resolvedPfxPath, $password, $storageFlags)
}
else {
$certificate = Get-CodeSigningCertificateFromStore -Thumbprint $CertificateThumbprint
}
if (-not $certificate.HasPrivateKey) {
throw "The selected certificate does not include a private key and cannot sign files."
}
$targets = foreach ($item in $Path) {
$resolvedPath = Resolve-FullPath $item
if (Test-Path -LiteralPath $resolvedPath -PathType Container) {
Get-ChildItem -LiteralPath $resolvedPath -Recurse -File |
Where-Object { $_.Extension -in ".exe", ".msi", ".dll", ".ps1", ".psm1", ".psd1", ".cat" }
}
elseif (Test-Path -LiteralPath $resolvedPath -PathType Leaf) {
Get-Item -LiteralPath $resolvedPath
}
else {
throw "Path not found: $resolvedPath"
}
}
if (-not $targets) {
throw "No files found to sign."
}
foreach ($target in $targets) {
Write-Host "Signing $($target.FullName)"
$signatureArguments = @{
FilePath = $target.FullName
Certificate = $certificate
HashAlgorithm = "SHA256"
}
if (-not $NoTimestamp -and $TimestampServer) {
$signatureArguments.TimestampServer = $TimestampServer
}
$signature = Set-AuthenticodeSignature @signatureArguments
if ($signature.Status -eq "UnknownError" -and $AllowUntrustedRoot -and $signature.SignerCertificate) {
Write-Warning "Signed $($target.FullName), but the local machine does not trust the signing root yet."
continue
}
if ($signature.Status -ne "Valid") {
throw "Signing failed for $($target.FullName): $($signature.StatusMessage)"
}
}
Write-Host "Signed $($targets.Count) file(s)."