[CmdletBinding(SupportsShouldProcess)] param( [string]$CertificatePath = ".\assets\certificates\MrSphay-LocalTrust-Root.cer", [string]$PublisherCertificatePath = ".\assets\certificates\MrSphay-CodeSigning.cer", [ValidateSet("CurrentUser", "LocalMachine")] [string]$Scope = "CurrentUser" ) $ErrorActionPreference = "Stop" function Resolve-FullPath { param([Parameter(Mandatory)][string]$Path) $executionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) } function Test-IsAdministrator { $identity = [Security.Principal.WindowsIdentity]::GetCurrent() $principal = [Security.Principal.WindowsPrincipal]::new($identity) $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) } $resolvedCertificatePath = Resolve-FullPath $CertificatePath if (-not (Test-Path -LiteralPath $resolvedCertificatePath)) { throw "Certificate file not found: $resolvedCertificatePath. Run scripts\New-MrTrustCertificate.ps1 first or provide -CertificatePath." } if ($Scope -eq "LocalMachine" -and -not (Test-IsAdministrator)) { throw "LocalMachine installation requires an elevated PowerShell session. Use -Scope CurrentUser or run as Administrator." } $rootCertificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($resolvedCertificatePath) if (-not $rootCertificate.Subject.StartsWith("CN=MrSphay", [System.StringComparison]::OrdinalIgnoreCase)) { throw "Refusing to install an unexpected root certificate subject: $($rootCertificate.Subject)" } $resolvedPublisherCertificatePath = Resolve-FullPath $PublisherCertificatePath $publisherCertificate = $null if (Test-Path -LiteralPath $resolvedPublisherCertificatePath) { $publisherCertificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($resolvedPublisherCertificatePath) if (-not $publisherCertificate.Subject.StartsWith("CN=MrSphay", [System.StringComparison]::OrdinalIgnoreCase)) { throw "Refusing to install an unexpected publisher certificate subject: $($publisherCertificate.Subject)" } } $rootStore = "Cert:\$Scope\Root" $publisherStore = "Cert:\$Scope\TrustedPublisher" Write-Host "MrTrust will install this certificate as trusted for scope '$Scope':" Write-Host " Root subject: $($rootCertificate.Subject)" Write-Host " Root issuer: $($rootCertificate.Issuer)" Write-Host " Root thumbprint: $($rootCertificate.Thumbprint)" Write-Host " Root expires: $($rootCertificate.NotAfter.ToString('yyyy-MM-dd HH:mm:ss'))" if ($publisherCertificate) { Write-Host " Publisher subject: $($publisherCertificate.Subject)" Write-Host " Publisher thumbprint: $($publisherCertificate.Thumbprint)" } else { Write-Warning "Publisher certificate not found at $resolvedPublisherCertificatePath. Only the root certificate will be installed." } Write-Host "" Write-Warning "Only continue if you trust MrSphay software signed with this certificate chain." $answer = Read-Host "Type INSTALL to continue" if ($answer -cne "INSTALL") { Write-Host "Installation cancelled." exit 1 } $existingRoot = Get-ChildItem -Path $rootStore | Where-Object Thumbprint -eq $rootCertificate.Thumbprint if (-not $existingRoot) { if ($PSCmdlet.ShouldProcess($rootStore, "Install MrTrust root certificate")) { Import-Certificate -FilePath $resolvedCertificatePath -CertStoreLocation $rootStore | Out-Null } } if ($publisherCertificate) { $existingPublisher = Get-ChildItem -Path $publisherStore | Where-Object Thumbprint -eq $publisherCertificate.Thumbprint if (-not $existingPublisher) { if ($PSCmdlet.ShouldProcess($publisherStore, "Install MrTrust trusted publisher certificate")) { Import-Certificate -FilePath $resolvedPublisherCertificatePath -CertStoreLocation $publisherStore | Out-Null } } } Write-Host "MrTrust certificate installed." Write-Host "Installed stores:" Write-Host " $rootStore" Write-Host " $publisherStore"