6 Commits

Author SHA1 Message Date
MrSphay
f5303fc536 Modernize MrTrust GUI
All checks were successful
Build MrTrust / build (push) Successful in 5m57s
2026-05-16 13:43:52 +02:00
MrSphay
a1819900b1 Fix GUI hover animation color capture
All checks were successful
Build MrTrust / build (push) Successful in 5m47s
2026-05-16 13:16:32 +02:00
MrSphay
46f9f95dcf Add diagnostics tab and UI animations
All checks were successful
Build MrTrust / build (push) Successful in 5m31s
2026-05-16 13:05:12 +02:00
MrSphay
8ce78741bb Make README a retro trust advertisement
All checks were successful
Build MrTrust / build (push) Successful in 4m13s
2026-05-16 04:13:17 +02:00
MrSphay
63f134e55e Update user-facing README
All checks were successful
Build MrTrust / build (push) Successful in 4m21s
2026-05-16 04:03:06 +02:00
MrSphay
e37a0b56c4 Limit release upload to push runs
All checks were successful
Build MrTrust / build (push) Successful in 4m24s
2026-05-16 03:28:54 +02:00
4 changed files with 707 additions and 268 deletions

View File

@@ -11,7 +11,7 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
MRTRUST_VERSION: 0.1.3 MRTRUST_VERSION: 0.1.4
steps: steps:
- name: Checkout - name: Checkout
@@ -59,7 +59,7 @@ jobs:
path: dist/MrTrust-${{ env.MRTRUST_VERSION }}.zip path: dist/MrTrust-${{ env.MRTRUST_VERSION }}.zip
- name: Attach ZIP to Gitea release - name: Attach ZIP to Gitea release
if: github.ref == 'refs/heads/main' if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'workflow_dispatch'
shell: bash shell: bash
env: env:
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,5 +1,12 @@
# Changelog # Changelog
## 0.1.4
- Added a diagnostics tab for checking `.exe`, `.msi`, `.dll`, and `.cat` files.
- Added signature status, MrSphay signer matching, and Mark-of-the-Web detection.
- Added an in-app SmartScreen explanation to clarify reputation versus local certificate trust.
- Added subtle Modrinth-style hover, press, progress, and accent animations.
## 0.1.3 ## 0.1.3
- Added Ubuntu-runner signing support through `osslsigncode` and PFX secrets. - Added Ubuntu-runner signing support through `osslsigncode` and PFX secrets.

282
README.md
View File

@@ -1,134 +1,240 @@
# MrTrust # MrTrust
MrTrust is a small Windows trust-onboarding kit for MrSphay software. ## Brought To You By The Fine People Of MrSphay
It is designed for this workflow: Good morning, citizen.
1. MrSphay creates a private code-signing certificate once. Has Windows ever looked at your freshly downloaded MrSphay program and said:
2. MrSphay publishes only the public trust certificate with MrTrust.
3. A user runs MrTrust once and explicitly approves installing that public certificate.
4. MrSphay projects signed with the matching certificate chain are shown as trusted on that PC.
MrTrust does not bypass Microsoft Defender or SmartScreen. Windows can still scan, quarantine, or warn about suspicious files. This project only manages normal Windows certificate trust with visible user consent. ```text
Unknown publisher? Sounds suspicious, pal.
## What It Contains
- `MrTrust.exe` opens a standalone Windows interface for installing or removing trust.
- `MrTrust.ps1` and `scripts/` are source and maintainer tools for building, signing, and local development.
- `scripts/New-MrTrustCertificate.ps1` creates a local root certificate and a code-signing certificate for the publisher.
- `scripts/Install-MrTrust.ps1` installs the public trust certificate for the current user or the local machine.
- `scripts/Uninstall-MrTrust.ps1` removes the MrTrust certificate again.
- `scripts/Sign-MrTrustProject.ps1` signs `.exe`, `.msi`, `.ps1`, and other Authenticode-compatible files.
- `scripts/Sign-MrTrustProjectLinux.sh` signs Windows PE/MSI/CAT artifacts on Ubuntu Gitea runners with `osslsigncode`.
- `scripts/New-MrTrustRelease.ps1` builds a distributable ZIP package.
- `docs/integration-prompt.md` is a prompt you can paste into other Windows projects.
- `docs/agent-target-integration.md` is the autonomous target-project integration runbook for agents.
- `mrtrust.integration.json` is the machine-readable integration contract.
- `MrTrust.exe` is standalone for normal users. It embeds the public certificates and runtime scripts.
## Quick Start For MrSphay
Create the certificates:
```powershell
.\scripts\New-MrTrustCertificate.ps1
``` ```
This writes: Then step right up to **MrTrust**, the cheerful little trust-onboarding utility that helps your PC recognize signed MrSphay software without poking holes in Windows security.
- public certificates to `assets\certificates\` One click. One confirmation. A brighter tomorrow for properly signed applications.
- private signing material to `private\`
The `private\` directory is ignored by git. Do not publish `.pfx` files or passwords. MrTrust installs public certificates only after you say so. It does not disable Microsoft Defender, SmartScreen, UAC, firewall rules, company policies, common sense, or the big red security lever nobody should touch.
Install the public trust certificate on your own PC: ## Download Your Complimentary Trust Appliance
```powershell Latest release page:
.\MrTrust.ps1 install
```text
https://git.wilkensxl.de/MrSphay/MrTrust/releases
``` ```
Open the GUI: Download the newest:
```powershell ```text
.\MrTrust.ps1 gui MrTrust-<version>.zip
``` ```
Sign another project build: Extract it, then run:
```powershell ```text
.\MrTrust.ps1 sign ` MrTrust.exe
-Path "C:\Path\To\App.exe" `
-PfxPath ".\private\MrSphay-CodeSigning.pfx"
``` ```
Remove the trust certificate: That is the normal user version. It is standalone and carries the public MrSphay certificates it needs.
```powershell ## Operating Your Trust-O-Matic 3000
.\MrTrust.ps1 uninstall
```
Build a user-facing ZIP release: Inside the friendly GUI:
```powershell - `Install trust` tells Windows to trust MrSphay public signing certificates.
.\scripts\New-MrTrustRelease.ps1 -Version 0.1.3 - `Remove trust` politely takes that trust back out again.
``` - `Refresh` checks whether your PC is currently feeling cooperative.
The Gitea workflow `.gitea/workflows/build.yml` builds the Windows launcher EXE on an `ubuntu-latest` runner with .NET Windows cross-targeting, then uploads the ZIP as an artifact. Default installation scope:
## User Installation
For normal users, distribute `MrTrust.exe`. The executable embeds the public certificate files and opens the GUI by default.
By default, MrTrust installs trust only for the current Windows user:
```text ```text
Root certificate -> Cert:\CurrentUser\Root Root certificate -> Cert:\CurrentUser\Root
Code-signing certificate -> Cert:\CurrentUser\TrustedPublisher Code-signing certificate -> Cert:\CurrentUser\TrustedPublisher
``` ```
For all users on the machine, run PowerShell as Administrator: That means the trust applies only to the current Windows user.
```powershell For all users on the PC, run `MrTrust.exe` as Administrator and choose the all-users option. Please operate administrator privileges responsibly. The future depends on it.
.\MrTrust.exe
## How The Magic Works
There is no magic. That is how you know it is working.
The approved flow:
1. A MrSphay app is signed during its release build.
2. You run `MrTrust.exe`.
3. You review the certificate details.
4. You confirm the trust installation.
5. Windows can validate signed MrSphay apps on that PC.
If the app is not signed, MrTrust cannot help it. Even the finest paperwork cannot identify a person who never showed up.
## Safety Notice From The Department Of Not Breaking Windows
MrTrust does not:
- make unsigned programs trusted
- bypass Defender
- bypass SmartScreen
- remove UAC prompts
- silently install certificates
- install private signing keys on user machines
- make sketchy software less sketchy
Windows may still scan, block, warn, quarantine, or ask questions. MrTrust only handles normal certificate trust.
## Public Certificate Values
These values are public and safe to use in documentation, agent prompts, and integration metadata:
```text
Publisher:
MrSphay
Root certificate thumbprint:
39F7458E6E2C1126E93E6A1F228196006B174DF2
Code-signing certificate thumbprint:
A024A89200469F099EC4A172B4F96F6428AFD41B
``` ```
Then choose the all-users option in the GUI. They are also stored here:
## Using This Repo With Other Agents ```text
assets/certificates/thumbprints.txt
mrtrust.integration.json
```
Yes. Give another agent this repository URL, the target Windows project, and `docs/integration-prompt.md`. ## For The Workshop Crew
For autonomous work, the agent should read these files in order: Local maintainer commands:
1. `mrtrust.integration.json` ```powershell
2. `docs/agent-target-integration.md` .\MrTrust.ps1 gui
3. `docs/integration-prompt.md` .\MrTrust.ps1 install
.\MrTrust.ps1 uninstall
```
The agent's job is to modify the target project, not this repository: Create or refresh local certificates:
- expose a visible "Open MrTrust" or trust setup path for users ```powershell
- link to or bundle the standalone `MrTrust.exe` .\scripts\New-MrTrustCertificate.ps1
- sign Windows release artifacts with the MrSphay code-signing certificate ```
- keep trust installation explicit, reversible, and user-confirmed
- keep private signing material out of the target repository and release artifacts
Both sides have to be wired: Build a release ZIP locally:
- MrTrust side: users install the public trust certificates once. ```powershell
- Target project side: release artifacts are signed with the MrSphay code-signing certificate. .\scripts\New-MrTrustRelease.ps1 -Version 0.1.4
- Installer side, optional: the target app can offer "Open MrTrust" or bundle `MrTrust.exe`, but it must not silently change trust. ```
If the target project is not signed, MrTrust cannot make it trusted. Sign an artifact locally on Windows:
## Important Limits ```powershell
.\MrTrust.ps1 sign `
-Path "C:\Path\To\App.exe" `
-CertificateThumbprint A024A89200469F099EC4A172B4F96F6428AFD41B
```
- This only helps for programs signed with the matching MrSphay certificate chain. Private signing material belongs only in:
- It does not make unsigned programs trusted.
- It does not disable Defender, SmartScreen, UAC, or enterprise policies.
- Public distribution without warnings is still best handled with a recognized commercial code-signing certificate.
## Recommended Project Integration ```text
private/
Bitwarden
Gitea repository secrets
```
Use `docs/integration-prompt.md` in another Windows project. The prompt tells Codex or another assistant to add a visible trust check, a link or bundled copy of the standalone `MrTrust.exe`, and a signing step without hiding security changes from the user. Never commit `.pfx` files, private keys, passwords, or Base64-encoded signing material. That is not trust. That is handing out the vault keys at the snack counter.
For agents that can inspect files autonomously, `docs/agent-target-integration.md` gives the decision tree, installer patterns, signing commands, and completion checklist. ## Gitea Secrets For Other Projects
For another project to sign Windows release artifacts on an Ubuntu Gitea runner, add these secrets to that target repository:
```text
MRTRUST_CODESIGN_PFX_BASE64
MRTRUST_CODESIGN_PFX_PASSWORD
```
Optional timestamp override:
```text
MRTRUST_TIMESTAMP_URL
```
The first two values are private signing credentials. Keep them in Bitwarden and Gitea Secrets only.
Ubuntu helper script:
```text
scripts/Sign-MrTrustProjectLinux.sh
```
It signs supported Windows artifacts with `osslsigncode`:
```text
.exe
.msi
.dll
.cat
```
PowerShell scripts should be signed on Windows, not Ubuntu.
## Installing MrTrust Into Another Project
Give your coding agent this repository:
```text
https://git.wilkensxl.de/MrSphay/MrTrust
```
Tell it to read:
```text
mrtrust.integration.json
docs/agent-target-integration.md
docs/integration-prompt.md
```
The target project should end up with:
- signed Windows release artifacts
- a visible optional MrTrust setup path
- a link to or bundled copy of `MrTrust.exe`
- documentation for installing and removing trust
- no committed private signing material
Remember the two-part handshake:
- MrTrust side: the user installs public trust certificates once.
- Target project side: the app is signed with the MrSphay code-signing certificate.
No signature, no trust. No trust, no victory parade.
## Current Build
The Gitea workflow builds `MrTrust.exe` on `ubuntu-latest` with .NET Windows cross-targeting.
On pushes to `main`, it:
1. builds the standalone Windows executable
2. packages `MrTrust-0.1.4.zip`
3. uploads the workflow artifact
4. attaches the ZIP to the Gitea release
Manual `workflow_dispatch` runs build artifacts but do not attach release assets. This prevents duplicate release uploads, which are bad for morale and paperwork.
## Final Safety Reminder
MrTrust is intentionally visible and reversible:
- the GUI shows the trust state
- installation requires confirmation
- removal is available in the same tool
- public certificates are embedded in the executable
- private signing material is never needed on user machines
For broad public distribution without SmartScreen reputation delays, a recognized commercial code-signing certificate is still the cleanest option.
Thank you for choosing MrTrust. Stay signed, stay verified, and keep your release pipeline tidy.

View File

@@ -10,6 +10,25 @@ $script:RootPath = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyComman
$script:RootCertificatePath = Join-Path $script:RootPath "assets\certificates\MrSphay-LocalTrust-Root.cer" $script:RootCertificatePath = Join-Path $script:RootPath "assets\certificates\MrSphay-LocalTrust-Root.cer"
$script:PublisherCertificatePath = Join-Path $script:RootPath "assets\certificates\MrSphay-CodeSigning.cer" $script:PublisherCertificatePath = Join-Path $script:RootPath "assets\certificates\MrSphay-CodeSigning.cer"
$script:IconPath = Join-Path $script:RootPath "assets\MrTrust.ico" $script:IconPath = Join-Path $script:RootPath "assets\MrTrust.ico"
$script:SelectedFilePath = $null
$script:CurrentAccent = 0
$colors = @{
Background = [Drawing.Color]::FromArgb(15, 20, 20)
Shell = [Drawing.Color]::FromArgb(20, 27, 27)
Panel = [Drawing.Color]::FromArgb(27, 36, 35)
PanelAlt = [Drawing.Color]::FromArgb(34, 45, 43)
PanelSelected = [Drawing.Color]::FromArgb(31, 64, 49)
Border = [Drawing.Color]::FromArgb(53, 66, 64)
Text = [Drawing.Color]::FromArgb(239, 244, 241)
Muted = [Drawing.Color]::FromArgb(157, 172, 166)
Green = [Drawing.Color]::FromArgb(0, 175, 91)
GreenHover = [Drawing.Color]::FromArgb(0, 199, 104)
GreenSoft = [Drawing.Color]::FromArgb(34, 76, 52)
Orange = [Drawing.Color]::FromArgb(242, 153, 74)
Red = [Drawing.Color]::FromArgb(235, 87, 87)
Blue = [Drawing.Color]::FromArgb(82, 166, 255)
}
function Test-IsAdministrator { function Test-IsAdministrator {
$identity = [Security.Principal.WindowsIdentity]::GetCurrent() $identity = [Security.Principal.WindowsIdentity]::GetCurrent()
@@ -28,12 +47,7 @@ function Get-MrTrustCertificate {
} }
function Get-TrustScope { function Get-TrustScope {
if ($script:AllUsersCheckBox.Checked) { if ($script:AllUsersCheckBox.Checked) { "LocalMachine" } else { "CurrentUser" }
"LocalMachine"
}
else {
"CurrentUser"
}
} }
function Get-StorePath { function Get-StorePath {
@@ -56,14 +70,153 @@ function Test-CertificateInstalled {
@(Get-ChildItem -Path $storePath | Where-Object Thumbprint -eq $Certificate.Thumbprint).Count -gt 0 @(Get-ChildItem -Path $storePath | Where-Object Thumbprint -eq $Certificate.Thumbprint).Count -gt 0
} }
function Set-StatusText { function Set-Busy {
param([Parameter(Mandatory)][string]$Text) param([bool]$Busy)
$script:StatusLabel.Text = $Text $script:ProgressBar.Visible = $Busy
if ($Busy) {
$script:ProgressBar.Style = "Marquee"
}
} }
function Refresh-MrTrustStatus { function Set-StatusText {
param(
[Parameter(Mandatory)][string]$Text,
[Parameter(Mandatory)][Drawing.Color]$Color
)
$script:StatusLabel.Text = $Text
$script:StatusPill.BackColor = $Color
}
function Add-AnimatedButton {
param(
[Parameter(Mandatory)][Windows.Forms.Button]$Button,
[Parameter(Mandatory)][Drawing.Color]$Normal,
[Parameter(Mandatory)][Drawing.Color]$Hover
)
$normalColor = $Normal
$hoverColor = $Hover
$textColor = $colors.Text
$borderColor = $colors.Border
$Button.FlatStyle = "Flat"
$Button.FlatAppearance.BorderColor = $borderColor
$Button.FlatAppearance.BorderSize = 1
$Button.BackColor = $normalColor
$Button.ForeColor = $textColor
$Button.Cursor = [Windows.Forms.Cursors]::Hand
$Button.Add_MouseEnter({ param($sender, $eventArgs) $sender.BackColor = $hoverColor }.GetNewClosure())
$Button.Add_MouseLeave({ param($sender, $eventArgs) $sender.BackColor = $normalColor }.GetNewClosure())
}
function New-Label {
param(
[string]$Text,
[int]$X,
[int]$Y,
[int]$Width = 220,
[int]$Height = 24,
[Drawing.Color]$Color = $colors.Muted,
[Drawing.Font]$Font = $null
)
$label = [Windows.Forms.Label]::new()
$label.Text = $Text
$label.Location = [Drawing.Point]::new($X, $Y)
$label.Size = [Drawing.Size]::new($Width, $Height)
$label.ForeColor = $Color
if ($Font) { $label.Font = $Font }
$label
}
function New-Card {
param(
[int]$X,
[int]$Y,
[int]$Width,
[int]$Height,
[Drawing.Color]$BackColor = $colors.Panel
)
$panel = [Windows.Forms.Panel]::new()
$panel.Location = [Drawing.Point]::new($X, $Y)
$panel.Size = [Drawing.Size]::new($Width, $Height)
$panel.BackColor = $BackColor
$panel.BorderStyle = "FixedSingle"
$panel.Anchor = "Top,Left,Right"
$panel
}
function New-PageTitle {
param(
[string]$Title,
[string]$Description
)
$titleLabel = New-Label -Text $Title -X 0 -Y 0 -Width 760 -Height 34 -Color $colors.Text -Font ([Drawing.Font]::new("Segoe UI", 15, [Drawing.FontStyle]::Bold))
$descriptionLabel = New-Label -Text $Description -X 1 -Y 38 -Width 850 -Height 24 -Color $colors.Muted
[pscustomobject]@{
Title = $titleLabel
Description = $descriptionLabel
}
}
function New-NavButton {
param(
[Parameter(Mandatory)][string]$Key,
[Parameter(Mandatory)][string]$Text,
[Parameter(Mandatory)][int]$Y
)
$button = [Windows.Forms.Button]::new()
$button.Text = $Text
$button.Tag = $Key
$button.Size = [Drawing.Size]::new(174, 44)
$button.Location = [Drawing.Point]::new(22, $Y)
$button.TextAlign = "MiddleLeft"
$button.Padding = [Windows.Forms.Padding]::new(14, 0, 0, 0)
$button.Font = [Drawing.Font]::new("Segoe UI", 10, [Drawing.FontStyle]::Bold)
$button.FlatStyle = "Flat"
$button.FlatAppearance.BorderSize = 1
$button.FlatAppearance.BorderColor = $colors.Shell
$button.BackColor = $colors.Shell
$button.ForeColor = $colors.Muted
$button.Cursor = [Windows.Forms.Cursors]::Hand
$button.Add_MouseEnter({ param($sender, $eventArgs) if ($script:ActivePage -ne $sender.Tag) { $sender.BackColor = $colors.PanelAlt } }.GetNewClosure())
$button.Add_MouseLeave({ param($sender, $eventArgs) if ($script:ActivePage -ne $sender.Tag) { $sender.BackColor = $colors.Shell } }.GetNewClosure())
$button.Add_Click({ param($sender, $eventArgs) Show-MrTrustPage -Key $sender.Tag })
$button
}
function Show-MrTrustPage {
param([Parameter(Mandatory)][string]$Key)
$script:ActivePage = $Key
foreach ($pageKey in $script:Pages.Keys) {
$script:Pages[$pageKey].Visible = $pageKey -eq $Key
}
foreach ($buttonKey in $script:NavButtons.Keys) {
$button = $script:NavButtons[$buttonKey]
if ($buttonKey -eq $Key) {
$button.BackColor = $colors.PanelSelected
$button.FlatAppearance.BorderColor = $colors.Green
$button.ForeColor = $colors.Text
}
else {
$button.BackColor = $colors.Shell
$button.FlatAppearance.BorderColor = $colors.Shell
$button.ForeColor = $colors.Muted
}
}
}
function Update-TrustStatus {
try { try {
Set-Busy $true
$rootCertificate = Get-MrTrustCertificate -Path $script:RootCertificatePath $rootCertificate = Get-MrTrustCertificate -Path $script:RootCertificatePath
$publisherCertificate = Get-MrTrustCertificate -Path $script:PublisherCertificatePath $publisherCertificate = Get-MrTrustCertificate -Path $script:PublisherCertificatePath
$scope = Get-TrustScope $scope = Get-TrustScope
@@ -74,79 +227,58 @@ function Refresh-MrTrustStatus {
$script:RootThumbprintLabel.Text = $rootCertificate.Thumbprint $script:RootThumbprintLabel.Text = $rootCertificate.Thumbprint
$script:PublisherThumbprintLabel.Text = $publisherCertificate.Thumbprint $script:PublisherThumbprintLabel.Text = $publisherCertificate.Thumbprint
$script:ExpiryLabel.Text = $rootCertificate.NotAfter.ToString("yyyy-MM-dd") $script:ExpiryLabel.Text = $rootCertificate.NotAfter.ToString("yyyy-MM-dd")
$script:ScopeValueLabel.Text = $scope
if ($rootInstalled -and $publisherInstalled) { if ($rootInstalled -and $publisherInstalled) {
Set-StatusText "Trusted" Set-StatusText -Text "Trusted" -Color $colors.Green
$script:StatusPill.BackColor = [Drawing.Color]::FromArgb(28, 185, 111) $script:TrustSummaryLabel.Text = "MrSphay public trust is installed for $scope."
} }
else { else {
Set-StatusText "Not installed" Set-StatusText -Text "Not installed" -Color $colors.Orange
$script:StatusPill.BackColor = [Drawing.Color]::FromArgb(242, 153, 74) $script:TrustSummaryLabel.Text = "Trust is not fully installed for $scope."
} }
} }
catch { catch {
Set-StatusText $_.Exception.Message Set-StatusText -Text "Error" -Color $colors.Red
$script:StatusPill.BackColor = [Drawing.Color]::FromArgb(235, 87, 87) $script:TrustSummaryLabel.Text = $_.Exception.Message
}
finally {
Set-Busy $false
} }
} }
function Install-MrTrustCertificates { function Install-MrTrustCertificates {
$scope = Get-TrustScope $scope = Get-TrustScope
if ($scope -eq "LocalMachine" -and -not (Test-IsAdministrator)) { if ($scope -eq "LocalMachine" -and -not (Test-IsAdministrator)) {
[Windows.Forms.MessageBox]::Show( [Windows.Forms.MessageBox]::Show("All-users trust requires running MrTrust as Administrator.", "MrTrust", "OK", "Warning") | Out-Null
"All-users trust requires running PowerShell as Administrator.",
"MrTrust",
[Windows.Forms.MessageBoxButtons]::OK,
[Windows.Forms.MessageBoxIcon]::Warning
) | Out-Null
return return
} }
$rootCertificate = Get-MrTrustCertificate -Path $script:RootCertificatePath $rootCertificate = Get-MrTrustCertificate -Path $script:RootCertificatePath
$publisherCertificate = Get-MrTrustCertificate -Path $script:PublisherCertificatePath $publisherCertificate = Get-MrTrustCertificate -Path $script:PublisherCertificatePath
$message = "Install MrSphay trust for $scope?`r`n`r`nRoot:`r`n$($rootCertificate.Thumbprint)`r`n`r`nPublisher:`r`n$($publisherCertificate.Thumbprint)`r`n`r`nThis does not disable Defender or SmartScreen."
$result = [Windows.Forms.MessageBox]::Show($message, "Install MrTrust", "YesNo", "Warning")
if ($result -ne [Windows.Forms.DialogResult]::Yes) { return }
$message = "Install MrSphay trust for $scope?`r`n`r`nRoot:`r`n$($rootCertificate.Thumbprint)`r`n`r`nPublisher:`r`n$($publisherCertificate.Thumbprint)`r`n`r`nOnly continue if you trust software signed by MrSphay." Set-Busy $true
$result = [Windows.Forms.MessageBox]::Show(
$message,
"Install MrTrust",
[Windows.Forms.MessageBoxButtons]::YesNo,
[Windows.Forms.MessageBoxIcon]::Warning
)
if ($result -ne [Windows.Forms.DialogResult]::Yes) {
return
}
Import-Certificate -FilePath $script:RootCertificatePath -CertStoreLocation (Get-StorePath -Scope $scope -Store "Root") | Out-Null Import-Certificate -FilePath $script:RootCertificatePath -CertStoreLocation (Get-StorePath -Scope $scope -Store "Root") | Out-Null
Import-Certificate -FilePath $script:PublisherCertificatePath -CertStoreLocation (Get-StorePath -Scope $scope -Store "TrustedPublisher") | Out-Null Import-Certificate -FilePath $script:PublisherCertificatePath -CertStoreLocation (Get-StorePath -Scope $scope -Store "TrustedPublisher") | Out-Null
Refresh-MrTrustStatus Update-TrustStatus
} }
function Remove-MrTrustCertificates { function Remove-MrTrustCertificates {
$scope = Get-TrustScope $scope = Get-TrustScope
if ($scope -eq "LocalMachine" -and -not (Test-IsAdministrator)) { if ($scope -eq "LocalMachine" -and -not (Test-IsAdministrator)) {
[Windows.Forms.MessageBox]::Show( [Windows.Forms.MessageBox]::Show("All-users removal requires running MrTrust as Administrator.", "MrTrust", "OK", "Warning") | Out-Null
"All-users removal requires running PowerShell as Administrator.",
"MrTrust",
[Windows.Forms.MessageBoxButtons]::OK,
[Windows.Forms.MessageBoxIcon]::Warning
) | Out-Null
return return
} }
$result = [Windows.Forms.MessageBox]::Show("Remove MrSphay trust for $scope?", "Remove MrTrust", "YesNo", "Question")
if ($result -ne [Windows.Forms.DialogResult]::Yes) { return }
Set-Busy $true
$rootCertificate = Get-MrTrustCertificate -Path $script:RootCertificatePath $rootCertificate = Get-MrTrustCertificate -Path $script:RootCertificatePath
$publisherCertificate = Get-MrTrustCertificate -Path $script:PublisherCertificatePath $publisherCertificate = Get-MrTrustCertificate -Path $script:PublisherCertificatePath
$result = [Windows.Forms.MessageBox]::Show(
"Remove MrSphay trust for $scope?",
"Remove MrTrust",
[Windows.Forms.MessageBoxButtons]::YesNo,
[Windows.Forms.MessageBoxIcon]::Question
)
if ($result -ne [Windows.Forms.DialogResult]::Yes) {
return
}
$targets = @( $targets = @(
[pscustomobject]@{ Store = "Root"; Thumbprint = $rootCertificate.Thumbprint }, [pscustomobject]@{ Store = "Root"; Thumbprint = $rootCertificate.Thumbprint },
[pscustomobject]@{ Store = "TrustedPublisher"; Thumbprint = $publisherCertificate.Thumbprint } [pscustomobject]@{ Store = "TrustedPublisher"; Thumbprint = $publisherCertificate.Thumbprint }
@@ -159,7 +291,86 @@ function Remove-MrTrustCertificates {
Remove-Item Remove-Item
} }
Refresh-MrTrustStatus Update-TrustStatus
}
function Test-MarkOfTheWeb {
param([Parameter(Mandatory)][string]$Path)
try {
$stream = Get-Content -LiteralPath $Path -Stream Zone.Identifier -ErrorAction Stop
($stream -join "`n") -match "ZoneId\s*=\s*[3-4]"
}
catch {
$false
}
}
function Get-SmartScreenExplanation {
param(
[bool]$SignedByMrSphay,
[bool]$HasMotw
)
if ($SignedByMrSphay -and $HasMotw) {
"Publisher trust can be valid while SmartScreen still warns because the downloaded file has Internet origin and low Microsoft reputation."
}
elseif ($SignedByMrSphay) {
"The publisher matches MrSphay. SmartScreen may still warn until Microsoft reputation builds for this exact app and publisher."
}
elseif ($HasMotw) {
"This file came from the Internet and is not signed by MrSphay. SmartScreen warnings are expected."
}
else {
"MrTrust can only help with MrSphay-signed files. SmartScreen reputation is separate from local certificate trust."
}
}
function Test-SelectedFile {
param([Parameter(Mandatory)][string]$Path)
Set-Busy $true
try {
if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
throw "File not found: $Path"
}
$signature = Get-AuthenticodeSignature -LiteralPath $Path
$hasMotw = Test-MarkOfTheWeb -Path $Path
$signer = $signature.SignerCertificate
$signedByMrSphay = $false
if ($signer) {
$signedByMrSphay = $signer.Thumbprint -eq "A024A89200469F099EC4A172B4F96F6428AFD41B" -or $signer.Subject -like "*MrSphay*"
}
$script:FileNameLabel.Text = [IO.Path]::GetFileName($Path)
$script:FilePathLabel.Text = $Path
$script:SignatureStatusLabel.Text = "$($signature.Status)"
$script:SignerLabel.Text = if ($signer) { $signer.Subject } else { "No signer certificate" }
$script:MrSphayMatchLabel.Text = if ($signedByMrSphay) { "Yes" } else { "No" }
$script:MotwLabel.Text = if ($hasMotw) { "Yes" } else { "No" }
$script:SmartScreenLabel.Text = Get-SmartScreenExplanation -SignedByMrSphay $signedByMrSphay -HasMotw $hasMotw
if ($signedByMrSphay -and $signature.Status -eq "Valid") {
$script:FileVerdictLabel.Text = "Looks good: signed by MrSphay and locally valid."
$script:FileVerdictLabel.ForeColor = $colors.Green
}
elseif ($signedByMrSphay) {
$script:FileVerdictLabel.Text = "Signed by MrSphay, but local validation is not fully valid: $($signature.Status)"
$script:FileVerdictLabel.ForeColor = $colors.Orange
}
else {
$script:FileVerdictLabel.Text = "Not a MrSphay-signed file."
$script:FileVerdictLabel.ForeColor = $colors.Red
}
}
catch {
$script:FileVerdictLabel.Text = $_.Exception.Message
$script:FileVerdictLabel.ForeColor = $colors.Red
}
finally {
Set-Busy $false
}
} }
[Windows.Forms.Application]::EnableVisualStyles() [Windows.Forms.Application]::EnableVisualStyles()
@@ -167,9 +378,9 @@ function Remove-MrTrustCertificates {
$form = [Windows.Forms.Form]::new() $form = [Windows.Forms.Form]::new()
$form.Text = "MrTrust" $form.Text = "MrTrust"
$form.StartPosition = "CenterScreen" $form.StartPosition = "CenterScreen"
$form.ClientSize = [Drawing.Size]::new(900, 560) $form.ClientSize = [Drawing.Size]::new(1120, 720)
$form.MinimumSize = [Drawing.Size]::new(860, 540) $form.MinimumSize = [Drawing.Size]::new(1040, 680)
$form.BackColor = [Drawing.Color]::FromArgb(22, 26, 29) $form.BackColor = $colors.Background
$form.Font = [Drawing.Font]::new("Segoe UI", 10) $form.Font = [Drawing.Font]::new("Segoe UI", 10)
if (Test-Path -LiteralPath $script:IconPath) { if (Test-Path -LiteralPath $script:IconPath) {
$form.Icon = [Drawing.Icon]::new($script:IconPath) $form.Icon = [Drawing.Icon]::new($script:IconPath)
@@ -177,170 +388,285 @@ if (Test-Path -LiteralPath $script:IconPath) {
$header = [Windows.Forms.Panel]::new() $header = [Windows.Forms.Panel]::new()
$header.Dock = "Top" $header.Dock = "Top"
$header.Height = 124 $header.Height = 96
$header.BackColor = [Drawing.Color]::FromArgb(27, 32, 35) $header.BackColor = $colors.Background
$form.Controls.Add($header) $form.Controls.Add($header)
$accent = [Windows.Forms.Panel]::new() $brandLine = [Windows.Forms.Panel]::new()
$accent.Dock = "Left" $brandLine.Dock = "Bottom"
$accent.Width = 8 $brandLine.Height = 1
$accent.BackColor = [Drawing.Color]::FromArgb(28, 185, 111) $brandLine.BackColor = $colors.Border
$header.Controls.Add($accent) $header.Controls.Add($brandLine)
$logoBox = [Windows.Forms.PictureBox]::new() $logoBox = [Windows.Forms.PictureBox]::new()
$logoBox.Size = [Drawing.Size]::new(44, 44) $logoBox.Size = [Drawing.Size]::new(42, 42)
$logoBox.Location = [Drawing.Point]::new(34, 30) $logoBox.Location = [Drawing.Point]::new(28, 26)
$logoBox.SizeMode = "StretchImage" $logoBox.SizeMode = "StretchImage"
if (Test-Path -LiteralPath $script:IconPath) { if (Test-Path -LiteralPath $script:IconPath) {
$logoBox.Image = [Drawing.Icon]::new($script:IconPath).ToBitmap() $logoBox.Image = [Drawing.Icon]::new($script:IconPath).ToBitmap()
} }
$header.Controls.Add($logoBox) $header.Controls.Add($logoBox)
$title = [Windows.Forms.Label]::new() $title = New-Label -Text "MrTrust" -X 86 -Y 20 -Width 260 -Height 36 -Color $colors.Text -Font ([Drawing.Font]::new("Segoe UI", 18, [Drawing.FontStyle]::Bold))
$title.Text = "MrTrust"
$title.ForeColor = [Drawing.Color]::White
$title.Font = [Drawing.Font]::new("Segoe UI", 24, [Drawing.FontStyle]::Bold)
$title.AutoSize = $true
$title.Location = [Drawing.Point]::new(92, 24)
$header.Controls.Add($title) $header.Controls.Add($title)
$subtitle = [Windows.Forms.Label]::new() $subtitle = New-Label -Text "Local certificate trust for MrSphay signed Windows apps" -X 88 -Y 56 -Width 520 -Height 24 -Color $colors.Muted
$subtitle.Text = "Trust setup for MrSphay signed Windows apps"
$subtitle.ForeColor = [Drawing.Color]::FromArgb(177, 190, 183)
$subtitle.AutoSize = $true
$subtitle.Location = [Drawing.Point]::new(96, 74)
$header.Controls.Add($subtitle) $header.Controls.Add($subtitle)
$statusText = [Windows.Forms.Label]::new() $statusCard = [Windows.Forms.Panel]::new()
$statusText.Text = "Status" $statusCard.Anchor = "Top,Right"
$statusText.ForeColor = [Drawing.Color]::FromArgb(177, 190, 183) $statusCard.Location = [Drawing.Point]::new(780, 20)
$statusText.AutoSize = $true $statusCard.Size = [Drawing.Size]::new(300, 56)
$statusText.Location = [Drawing.Point]::new(646, 32) $statusCard.BackColor = $colors.Panel
$header.Controls.Add($statusText) $statusCard.BorderStyle = "FixedSingle"
$header.Controls.Add($statusCard)
$statusText = New-Label -Text "Trust status" -X 18 -Y 7 -Width 130 -Height 20 -Color $colors.Muted -Font ([Drawing.Font]::new("Segoe UI", 8.5))
$statusCard.Controls.Add($statusText)
$script:StatusPill = [Windows.Forms.Panel]::new() $script:StatusPill = [Windows.Forms.Panel]::new()
$script:StatusPill.Size = [Drawing.Size]::new(16, 16) $script:StatusPill.Size = [Drawing.Size]::new(14, 14)
$script:StatusPill.Location = [Drawing.Point]::new(646, 62) $script:StatusPill.Location = [Drawing.Point]::new(18, 31)
$script:StatusPill.BackColor = [Drawing.Color]::FromArgb(242, 153, 74) $script:StatusPill.BackColor = $colors.Orange
$header.Controls.Add($script:StatusPill) $statusCard.Controls.Add($script:StatusPill)
$script:StatusLabel = [Windows.Forms.Label]::new() $script:StatusLabel = New-Label -Text "Checking..." -X 40 -Y 26 -Width 210 -Height 24 -Color $colors.Text -Font ([Drawing.Font]::new("Segoe UI", 10, [Drawing.FontStyle]::Bold))
$script:StatusLabel.Text = "Checking..."
$script:StatusLabel.ForeColor = [Drawing.Color]::FromArgb(225, 231, 227)
$script:StatusLabel.AutoSize = $false
$script:StatusLabel.AutoEllipsis = $true $script:StatusLabel.AutoEllipsis = $true
$script:StatusLabel.Location = [Drawing.Point]::new(674, 57) $statusCard.Controls.Add($script:StatusLabel)
$script:StatusLabel.Size = [Drawing.Size]::new(190, 28)
$header.Controls.Add($script:StatusLabel)
$content = [Windows.Forms.Panel]::new() $script:ProgressBar = [Windows.Forms.ProgressBar]::new()
$content.Dock = "Fill" $script:ProgressBar.Anchor = "Top,Left,Right"
$content.Padding = [Windows.Forms.Padding]::new(30) $script:ProgressBar.Location = [Drawing.Point]::new(28, 86)
$content.BackColor = [Drawing.Color]::FromArgb(22, 26, 29) $script:ProgressBar.Size = [Drawing.Size]::new(1052, 4)
$form.Controls.Add($content) $script:ProgressBar.Visible = $false
$header.Controls.Add($script:ProgressBar)
$infoPanel = [Windows.Forms.Panel]::new() $shell = [Windows.Forms.Panel]::new()
$infoPanel.BackColor = [Drawing.Color]::FromArgb(31, 37, 40) $shell.Dock = "Fill"
$infoPanel.Size = [Drawing.Size]::new(820, 226) $shell.BackColor = $colors.Background
$infoPanel.Location = [Drawing.Point]::new(40, 34) $form.Controls.Add($shell)
$content.Controls.Add($infoPanel)
$scopeLabel = [Windows.Forms.Label]::new() $sidebar = [Windows.Forms.Panel]::new()
$scopeLabel.Text = "Scope" $sidebar.Dock = "Left"
$scopeLabel.ForeColor = [Drawing.Color]::FromArgb(177, 190, 183) $sidebar.Width = 220
$scopeLabel.Location = [Drawing.Point]::new(24, 24) $sidebar.BackColor = $colors.Shell
$scopeLabel.AutoSize = $true $shell.Controls.Add($sidebar)
$infoPanel.Controls.Add($scopeLabel)
$sideAccent = [Windows.Forms.Panel]::new()
$sideAccent.Dock = "Left"
$sideAccent.Width = 4
$sideAccent.BackColor = $colors.Green
$sidebar.Controls.Add($sideAccent)
$navTitle = New-Label -Text "Navigation" -X 24 -Y 26 -Width 160 -Height 22 -Color $colors.Muted -Font ([Drawing.Font]::new("Segoe UI", 8.5, [Drawing.FontStyle]::Bold))
$sidebar.Controls.Add($navTitle)
$script:NavButtons = @{}
$script:NavButtons.Trust = New-NavButton -Key "Trust" -Text "Trust" -Y 58
$script:NavButtons.Diagnostics = New-NavButton -Key "Diagnostics" -Text "File scan" -Y 110
$script:NavButtons.SmartScreen = New-NavButton -Key "SmartScreen" -Text "SmartScreen" -Y 162
foreach ($navButton in $script:NavButtons.Values) {
$sidebar.Controls.Add($navButton)
}
$sideNote = New-Label -Text "Installs public certificates only. No Defender, SmartScreen, UAC, firewall, or policy bypasses." -X 24 -Y 510 -Width 164 -Height 96 -Color $colors.Muted -Font ([Drawing.Font]::new("Segoe UI", 8.5))
$sideNote.Anchor = "Left,Bottom"
$sidebar.Controls.Add($sideNote)
$contentHost = [Windows.Forms.Panel]::new()
$contentHost.Dock = "Fill"
$contentHost.BackColor = $colors.Background
$contentHost.Padding = [Windows.Forms.Padding]::new(34, 30, 34, 30)
$shell.Controls.Add($contentHost)
$script:Pages = @{}
$trustPage = [Windows.Forms.Panel]::new()
$trustPage.Dock = "Fill"
$trustPage.BackColor = $colors.Background
$contentHost.Controls.Add($trustPage)
$script:Pages.Trust = $trustPage
$trustTitle = New-PageTitle -Title "Trust" -Description "Install, remove, and verify the MrSphay public trust certificates."
$trustPage.Controls.Add($trustTitle.Title)
$trustPage.Controls.Add($trustTitle.Description)
$trustPanel = New-Card -X 0 -Y 82 -Width 820 -Height 236
$trustPage.Controls.Add($trustPanel)
$scopeLabel = New-Label -Text "Scope" -X 24 -Y 22 -Width 160 -Height 22 -Color $colors.Muted -Font ([Drawing.Font]::new("Segoe UI", 8.5, [Drawing.FontStyle]::Bold))
$trustPanel.Controls.Add($scopeLabel)
$script:AllUsersCheckBox = [Windows.Forms.CheckBox]::new() $script:AllUsersCheckBox = [Windows.Forms.CheckBox]::new()
$script:AllUsersCheckBox.Text = "Install for all users (requires Administrator)" $script:AllUsersCheckBox.Text = "All users (LocalMachine, requires Administrator)"
$script:AllUsersCheckBox.ForeColor = [Drawing.Color]::FromArgb(225, 231, 227) $script:AllUsersCheckBox.ForeColor = $colors.Text
$script:AllUsersCheckBox.Location = [Drawing.Point]::new(24, 50) $script:AllUsersCheckBox.Location = [Drawing.Point]::new(24, 46)
$script:AllUsersCheckBox.AutoSize = $true $script:AllUsersCheckBox.AutoSize = $true
$script:AllUsersCheckBox.FlatStyle = "Flat" $script:AllUsersCheckBox.FlatStyle = "Flat"
$script:AllUsersCheckBox.Add_CheckedChanged({ Refresh-MrTrustStatus }) $script:AllUsersCheckBox.Add_CheckedChanged({ Update-TrustStatus })
$infoPanel.Controls.Add($script:AllUsersCheckBox) $trustPanel.Controls.Add($script:AllUsersCheckBox)
$rootLabel = [Windows.Forms.Label]::new() $trustPanel.Controls.Add((New-Label -Text "Root thumbprint" -X 24 -Y 90 -Width 170 -Height 24))
$rootLabel.Text = "Root thumbprint" $script:RootThumbprintLabel = New-Label -Text "-" -X 210 -Y 90 -Width 560 -Height 24 -Color $colors.Text -Font ([Drawing.Font]::new("Consolas", 9))
$rootLabel.ForeColor = [Drawing.Color]::FromArgb(177, 190, 183) $script:RootThumbprintLabel.AutoEllipsis = $true
$rootLabel.Location = [Drawing.Point]::new(24, 92) $trustPanel.Controls.Add($script:RootThumbprintLabel)
$rootLabel.AutoSize = $true
$infoPanel.Controls.Add($rootLabel)
$script:RootThumbprintLabel = [Windows.Forms.Label]::new() $trustPanel.Controls.Add((New-Label -Text "Publisher thumbprint" -X 24 -Y 124 -Width 170 -Height 24))
$script:RootThumbprintLabel.Text = "-" $script:PublisherThumbprintLabel = New-Label -Text "-" -X 210 -Y 124 -Width 560 -Height 24 -Color $colors.Text -Font ([Drawing.Font]::new("Consolas", 9))
$script:RootThumbprintLabel.ForeColor = [Drawing.Color]::FromArgb(225, 231, 227) $script:PublisherThumbprintLabel.AutoEllipsis = $true
$script:RootThumbprintLabel.Font = [Drawing.Font]::new("Consolas", 9) $trustPanel.Controls.Add($script:PublisherThumbprintLabel)
$script:RootThumbprintLabel.Location = [Drawing.Point]::new(180, 92)
$script:RootThumbprintLabel.AutoSize = $true
$infoPanel.Controls.Add($script:RootThumbprintLabel)
$publisherLabel = [Windows.Forms.Label]::new() $trustPanel.Controls.Add((New-Label -Text "Expires" -X 24 -Y 158 -Width 170 -Height 24))
$publisherLabel.Text = "Publisher thumbprint" $script:ExpiryLabel = New-Label -Text "-" -X 210 -Y 158 -Width 180 -Height 24 -Color $colors.Text
$publisherLabel.ForeColor = [Drawing.Color]::FromArgb(177, 190, 183) $trustPanel.Controls.Add($script:ExpiryLabel)
$publisherLabel.Location = [Drawing.Point]::new(24, 128)
$publisherLabel.AutoSize = $true
$infoPanel.Controls.Add($publisherLabel)
$script:PublisherThumbprintLabel = [Windows.Forms.Label]::new() $trustPanel.Controls.Add((New-Label -Text "Active scope" -X 24 -Y 192 -Width 170 -Height 24))
$script:PublisherThumbprintLabel.Text = "-" $script:ScopeValueLabel = New-Label -Text "-" -X 210 -Y 192 -Width 200 -Height 24 -Color $colors.Text
$script:PublisherThumbprintLabel.ForeColor = [Drawing.Color]::FromArgb(225, 231, 227) $trustPanel.Controls.Add($script:ScopeValueLabel)
$script:PublisherThumbprintLabel.Font = [Drawing.Font]::new("Consolas", 9)
$script:PublisherThumbprintLabel.Location = [Drawing.Point]::new(180, 128)
$script:PublisherThumbprintLabel.AutoSize = $true
$infoPanel.Controls.Add($script:PublisherThumbprintLabel)
$expiryLabelTitle = [Windows.Forms.Label]::new() $summaryPanel = New-Card -X 0 -Y 338 -Width 820 -Height 76 -BackColor $colors.PanelAlt
$expiryLabelTitle.Text = "Expires" $trustPage.Controls.Add($summaryPanel)
$expiryLabelTitle.ForeColor = [Drawing.Color]::FromArgb(177, 190, 183)
$expiryLabelTitle.Location = [Drawing.Point]::new(24, 164)
$expiryLabelTitle.AutoSize = $true
$infoPanel.Controls.Add($expiryLabelTitle)
$script:ExpiryLabel = [Windows.Forms.Label]::new() $script:TrustSummaryLabel = New-Label -Text "Checking trust state..." -X 22 -Y 18 -Width 760 -Height 34 -Color $colors.Text -Font ([Drawing.Font]::new("Segoe UI", 10, [Drawing.FontStyle]::Bold))
$script:ExpiryLabel.Text = "-" $summaryPanel.Controls.Add($script:TrustSummaryLabel)
$script:ExpiryLabel.ForeColor = [Drawing.Color]::FromArgb(225, 231, 227)
$script:ExpiryLabel.Location = [Drawing.Point]::new(180, 164)
$script:ExpiryLabel.AutoSize = $true
$infoPanel.Controls.Add($script:ExpiryLabel)
$installButton = [Windows.Forms.Button]::new() $installButton = [Windows.Forms.Button]::new()
$installButton.Text = "Install trust" $installButton.Text = "Install trust"
$installButton.BackColor = [Drawing.Color]::FromArgb(28, 185, 111) $installButton.Size = [Drawing.Size]::new(160, 44)
$installButton.ForeColor = [Drawing.Color]::White $installButton.Location = [Drawing.Point]::new(0, 438)
$installButton.FlatStyle = "Flat" Add-AnimatedButton -Button $installButton -Normal $colors.Green -Hover $colors.GreenHover
$installButton.Size = [Drawing.Size]::new(180, 46)
$installButton.Location = [Drawing.Point]::new(40, 292)
$installButton.Add_Click({ Install-MrTrustCertificates }) $installButton.Add_Click({ Install-MrTrustCertificates })
$content.Controls.Add($installButton) $trustPage.Controls.Add($installButton)
$removeButton = [Windows.Forms.Button]::new() $removeButton = [Windows.Forms.Button]::new()
$removeButton.Text = "Remove trust" $removeButton.Text = "Remove trust"
$removeButton.BackColor = [Drawing.Color]::FromArgb(44, 52, 56) $removeButton.Size = [Drawing.Size]::new(160, 44)
$removeButton.ForeColor = [Drawing.Color]::FromArgb(225, 231, 227) $removeButton.Location = [Drawing.Point]::new(176, 438)
$removeButton.FlatStyle = "Flat" Add-AnimatedButton -Button $removeButton -Normal $colors.PanelAlt -Hover $colors.Border
$removeButton.Size = [Drawing.Size]::new(180, 46)
$removeButton.Location = [Drawing.Point]::new(240, 292)
$removeButton.Add_Click({ Remove-MrTrustCertificates }) $removeButton.Add_Click({ Remove-MrTrustCertificates })
$content.Controls.Add($removeButton) $trustPage.Controls.Add($removeButton)
$refreshButton = [Windows.Forms.Button]::new() $refreshButton = [Windows.Forms.Button]::new()
$refreshButton.Text = "Refresh" $refreshButton.Text = "Refresh"
$refreshButton.BackColor = [Drawing.Color]::FromArgb(44, 52, 56) $refreshButton.Size = [Drawing.Size]::new(124, 44)
$refreshButton.ForeColor = [Drawing.Color]::FromArgb(225, 231, 227) $refreshButton.Location = [Drawing.Point]::new(352, 438)
$refreshButton.FlatStyle = "Flat" Add-AnimatedButton -Button $refreshButton -Normal $colors.PanelAlt -Hover $colors.Border
$refreshButton.Size = [Drawing.Size]::new(140, 46) $refreshButton.Add_Click({ Update-TrustStatus })
$refreshButton.Location = [Drawing.Point]::new(440, 292) $trustPage.Controls.Add($refreshButton)
$refreshButton.Add_Click({ Refresh-MrTrustStatus })
$content.Controls.Add($refreshButton)
$note = [Windows.Forms.Label]::new() $note = New-Label -Text "Trust actions are reversible and scoped to the selected Windows certificate store." -X 0 -Y 508 -Width 820 -Height 26 -Color $colors.Muted
$note.Text = "MrTrust installs public certificates only. It does not disable Defender, SmartScreen, UAC, or enterprise policies." $trustPage.Controls.Add($note)
$note.ForeColor = [Drawing.Color]::FromArgb(177, 190, 183)
$note.Location = [Drawing.Point]::new(40, 376)
$note.Size = [Drawing.Size]::new(820, 48)
$content.Controls.Add($note)
$form.Add_Shown({ Refresh-MrTrustStatus }) $diagnosticsPage = [Windows.Forms.Panel]::new()
$diagnosticsPage.Dock = "Fill"
$diagnosticsPage.BackColor = $colors.Background
$diagnosticsPage.Visible = $false
$contentHost.Controls.Add($diagnosticsPage)
$script:Pages.Diagnostics = $diagnosticsPage
$diagnosticsTitle = New-PageTitle -Title "File scan" -Description "Inspect a Windows executable, installer, catalog, or DLL for signature and origin signals."
$diagnosticsPage.Controls.Add($diagnosticsTitle.Title)
$diagnosticsPage.Controls.Add($diagnosticsTitle.Description)
$filePanel = New-Card -X 0 -Y 82 -Width 820 -Height 420
$diagnosticsPage.Controls.Add($filePanel)
$chooseButton = [Windows.Forms.Button]::new()
$chooseButton.Text = "Choose file"
$chooseButton.Size = [Drawing.Size]::new(150, 42)
$chooseButton.Location = [Drawing.Point]::new(24, 24)
Add-AnimatedButton -Button $chooseButton -Normal $colors.Green -Hover $colors.GreenHover
$filePanel.Controls.Add($chooseButton)
$scanButton = [Windows.Forms.Button]::new()
$scanButton.Text = "Scan again"
$scanButton.Size = [Drawing.Size]::new(130, 42)
$scanButton.Location = [Drawing.Point]::new(190, 24)
Add-AnimatedButton -Button $scanButton -Normal $colors.PanelAlt -Hover $colors.Border
$filePanel.Controls.Add($scanButton)
$script:FileVerdictLabel = New-Label -Text "Choose a Windows app or installer to inspect." -X 24 -Y 88 -Width 760 -Height 30 -Color $colors.Muted -Font ([Drawing.Font]::new("Segoe UI", 11, [Drawing.FontStyle]::Bold))
$filePanel.Controls.Add($script:FileVerdictLabel)
$filePanel.Controls.Add((New-Label -Text "File" -X 24 -Y 136 -Width 170 -Height 24))
$script:FileNameLabel = New-Label -Text "-" -X 210 -Y 136 -Width 560 -Height 24 -Color $colors.Text
$script:FileNameLabel.AutoEllipsis = $true
$filePanel.Controls.Add($script:FileNameLabel)
$filePanel.Controls.Add((New-Label -Text "Path" -X 24 -Y 170 -Width 170 -Height 24))
$script:FilePathLabel = New-Label -Text "-" -X 210 -Y 170 -Width 560 -Height 40 -Color $colors.Text
$script:FilePathLabel.AutoEllipsis = $true
$filePanel.Controls.Add($script:FilePathLabel)
$filePanel.Controls.Add((New-Label -Text "Signature status" -X 24 -Y 222 -Width 170 -Height 24))
$script:SignatureStatusLabel = New-Label -Text "-" -X 210 -Y 222 -Width 560 -Height 24 -Color $colors.Text
$filePanel.Controls.Add($script:SignatureStatusLabel)
$filePanel.Controls.Add((New-Label -Text "Signer" -X 24 -Y 256 -Width 170 -Height 24))
$script:SignerLabel = New-Label -Text "-" -X 210 -Y 256 -Width 560 -Height 36 -Color $colors.Text
$script:SignerLabel.AutoEllipsis = $true
$filePanel.Controls.Add($script:SignerLabel)
$filePanel.Controls.Add((New-Label -Text "MrSphay match" -X 24 -Y 306 -Width 170 -Height 24))
$script:MrSphayMatchLabel = New-Label -Text "-" -X 210 -Y 306 -Width 160 -Height 24 -Color $colors.Text
$filePanel.Controls.Add($script:MrSphayMatchLabel)
$filePanel.Controls.Add((New-Label -Text "Mark-of-the-Web" -X 390 -Y 306 -Width 160 -Height 24))
$script:MotwLabel = New-Label -Text "-" -X 560 -Y 306 -Width 160 -Height 24 -Color $colors.Text
$filePanel.Controls.Add($script:MotwLabel)
$filePanel.Controls.Add((New-Label -Text "SmartScreen note" -X 24 -Y 352 -Width 170 -Height 24))
$script:SmartScreenLabel = New-Label -Text "-" -X 210 -Y 352 -Width 560 -Height 48 -Color $colors.Muted
$filePanel.Controls.Add($script:SmartScreenLabel)
$chooseButton.Add_Click({
$dialog = [Windows.Forms.OpenFileDialog]::new()
$dialog.Filter = "Windows apps and installers (*.exe;*.msi;*.dll;*.cat)|*.exe;*.msi;*.dll;*.cat|All files (*.*)|*.*"
if ($dialog.ShowDialog() -eq [Windows.Forms.DialogResult]::OK) {
$script:SelectedFilePath = $dialog.FileName
Test-SelectedFile -Path $script:SelectedFilePath
}
})
$scanButton.Add_Click({
if ($script:SelectedFilePath) {
Test-SelectedFile -Path $script:SelectedFilePath
}
})
$helpPage = [Windows.Forms.Panel]::new()
$helpPage.Dock = "Fill"
$helpPage.BackColor = $colors.Background
$helpPage.Visible = $false
$contentHost.Controls.Add($helpPage)
$script:Pages.SmartScreen = $helpPage
$helpTitle = New-PageTitle -Title "SmartScreen" -Description "Understand what MrTrust can verify and what Windows reputation still controls."
$helpPage.Controls.Add($helpTitle.Title)
$helpPage.Controls.Add($helpTitle.Description)
$helpPanel = New-Card -X 0 -Y 82 -Width 820 -Height 330
$helpPage.Controls.Add($helpPanel)
$helpPanel.Controls.Add((New-Label -Text "Local trust" -X 24 -Y 24 -Width 180 -Height 24 -Color $colors.Text -Font ([Drawing.Font]::new("Segoe UI", 11, [Drawing.FontStyle]::Bold))))
$helpPanel.Controls.Add((New-Label -Text "MrTrust installs the public MrSphay root and publisher certificates into the selected Windows certificate stores." -X 24 -Y 54 -Width 740 -Height 42 -Color $colors.Muted))
$helpPanel.Controls.Add((New-Label -Text "Windows reputation" -X 24 -Y 118 -Width 220 -Height 24 -Color $colors.Text -Font ([Drawing.Font]::new("Segoe UI", 11, [Drawing.FontStyle]::Bold))))
$helpPanel.Controls.Add((New-Label -Text "SmartScreen can still warn for a new or rarely downloaded file, even when the signature is valid and the publisher is recognized." -X 24 -Y 148 -Width 740 -Height 42 -Color $colors.Muted))
$helpPanel.Controls.Add((New-Label -Text "What to check" -X 24 -Y 212 -Width 180 -Height 24 -Color $colors.Text -Font ([Drawing.Font]::new("Segoe UI", 11, [Drawing.FontStyle]::Bold))))
$helpPanel.Controls.Add((New-Label -Text "Use File scan to verify signature status, MrSphay signer matching, and Mark-of-the-Web. MrTrust never disables SmartScreen." -X 24 -Y 242 -Width 740 -Height 46 -Color $colors.Muted))
$pulseTimer = [Windows.Forms.Timer]::new()
$pulseTimer.Interval = 100
$pulseTimer.Add_Tick({
$script:CurrentAccent = ($script:CurrentAccent + 1) % 40
$value = 130 + [Math]::Abs(20 - $script:CurrentAccent) * 4
$sideAccent.BackColor = [Drawing.Color]::FromArgb(0, [Math]::Min(205, $value), 91)
})
$pulseTimer.Start()
$form.Add_Shown({
Show-MrTrustPage -Key "Trust"
Update-TrustStatus
})
[Windows.Forms.Application]::Run($form) [Windows.Forms.Application]::Run($form)