Private/Test-NartacBinary.ps1
|
function Test-NartacBinary { <# .SYNOPSIS Verifies an Authenticode-signed Nartac binary and (optionally) its SHA256 hash. .DESCRIPTION Performs defence-in-depth verification on a downloaded Nartac Software binary (e.g. IISCryptoCli.exe or IISCrypto.exe) before it is moved into a trusted location. Always validates the Authenticode signature and checks that the signer certificate Subject contains the expected publisher substring (default 'Nartac'). When -ExpectedSha256 is supplied, additionally compares the file's SHA256 hash against the supplied value (case-insensitive). On failure, this function throws a terminating error via Write-Error -ErrorAction Stop. It does NOT delete the file under inspection; callers are responsible for cleanup of quarantined artefacts. .PARAMETER Path Full path to the file under verification. .PARAMETER ExpectedSha256 Optional SHA256 hash (hex, any case). When supplied, the file hash must match exactly (case-insensitive) or verification fails. .PARAMETER ExpectedPublisherSubstring Substring that must appear in the Authenticode signer certificate Subject. Defaults to 'Nartac'. .EXAMPLE Test-NartacBinary -Path "$env:TEMP\IISCryptoCli.exe" Validates the Authenticode signature only and returns $true on success. .EXAMPLE Test-NartacBinary -Path "$env:TEMP\IISCryptoCli.exe" -ExpectedSha256 'ABCDEF...' Validates the Authenticode signature and confirms the SHA256 matches. .NOTES Internal helper for Install-IISCrypto and Update-IISCrypto. Does not perform cleanup; callers should Remove-Item the file on verification failure. #> [CmdletBinding()] [OutputType([bool])] param( [Parameter(Mandatory = $true)] [string]$Path, [Parameter(Mandatory = $false)] [string]$ExpectedSha256, [Parameter(Mandatory = $false)] [string]$ExpectedPublisherSubstring = 'Nartac' ) if (-not (Test-Path -Path $Path)) { Write-Error -Category ObjectNotFound -Message "File not found: $Path" -ErrorAction Stop } $sig = Get-AuthenticodeSignature -FilePath $Path $subject = if ($sig.SignerCertificate) { $sig.SignerCertificate.Subject } else { '<no signer>' } $publisherPattern = "*$ExpectedPublisherSubstring*" if ($sig.Status -ne 'Valid' -or -not ($subject -like $publisherPattern)) { Write-Error -Category SecurityError -Message "Authenticode verification failed for ${Path}: Status=$($sig.Status); Subject=$subject" -ErrorAction Stop } if ($PSBoundParameters.ContainsKey('ExpectedSha256') -and -not [string]::IsNullOrWhiteSpace($ExpectedSha256)) { $actual = (Get-FileHash -Path $Path -Algorithm SHA256).Hash.ToUpperInvariant() $expected = $ExpectedSha256.ToUpperInvariant() if ($actual -ne $expected) { Write-Error -Category SecurityError -Message "SHA256 mismatch for ${Path}: expected $expected; actual $actual" -ErrorAction Stop } } return $true } |