This guide explains how to create and manage code signing certificates for MouseEffects.
MSIX packages must be signed with a valid certificate. The certificate's publisher name must match the Publisher attribute in the package manifest.
| Type | Use Case | Trust Level |
|---|---|---|
| Self-Signed | Development, internal testing | Manual trust installation |
| Enterprise | Corporate deployment | Trusted via Group Policy |
| EV Code Signing | Public distribution | Trusted by Windows |
| Microsoft Store | Store apps | Signed by Microsoft |
Run PowerShell as Administrator:
# Create self-signed certificate
$cert = New-SelfSignedCertificate `
-Type Custom `
-Subject "CN=MouseEffects Dev" `
-KeyUsage DigitalSignature `
-FriendlyName "MouseEffects Development" `
-CertStoreLocation "Cert:\CurrentUser\My" `
-TextExtension @(
"2.5.29.37={text}1.3.6.1.5.5.7.3.3", # Code Signing
"2.5.29.19={text}" # Basic Constraints
)
# Display thumbprint
Write-Host "Certificate Thumbprint: $($cert.Thumbprint)"Add the thumbprint to your project:
- Copy the thumbprint output
- Add to
MouseEffects.App.csproj:<PackageCertificateThumbprint>YOUR_THUMBPRINT</PackageCertificateThumbprint>
Or update packaging\build-msix.ps1 default parameter.
Export the public certificate for users to install:
# Export public certificate (.cer)
$thumbprint = "YOUR_THUMBPRINT"
$cert = Get-ChildItem -Path "Cert:\CurrentUser\My\$thumbprint"
Export-Certificate -Cert $cert -FilePath "MouseEffects-Dev.cer"Or use the provided script:
.\packaging\export-cert.ps1Users must install your certificate before they can install the MSIX:
- Double-click
MouseEffects-Dev.cer - Click Install Certificate
- Select Local Machine
- Select Place all certificates in the following store
- Click Browse → Select Trusted Root Certification Authorities
- Click Next → Finish
# Import certificate to Trusted Root
Import-Certificate `
-FilePath "MouseEffects-Dev.cer" `
-CertStoreLocation "Cert:\LocalMachine\Root"certutil -addstore Root MouseEffects-Dev.cerWindows stores certificates in different locations:
| Store | Path | Purpose |
|---|---|---|
| Current User - Personal | Cert:\CurrentUser\My |
Your signing certificates |
| Local Machine - Root | Cert:\LocalMachine\Root |
Trusted root CAs |
| Local Machine - TrustedPublisher | Cert:\LocalMachine\TrustedPublisher |
Trusted code signers |
# List your signing certificates
Get-ChildItem -Path "Cert:\CurrentUser\My" -CodeSigningCert
# List trusted roots
Get-ChildItem -Path "Cert:\LocalMachine\Root"Or use the Certificate Manager GUI:
certmgr.msc$signtool = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64\signtool.exe"
# Sign with thumbprint
& $signtool sign `
/sha1 YOUR_THUMBPRINT `
/fd SHA256 `
/td SHA256 `
/tr http://timestamp.digicert.com `
MouseEffects.msix| Option | Description |
|---|---|
/sha1 |
Certificate thumbprint |
/fd SHA256 |
File digest algorithm |
/td SHA256 |
Timestamp digest algorithm |
/tr |
Timestamp server URL |
Always use a timestamp server for production:
| Provider | URL |
|---|---|
| DigiCert | http://timestamp.digicert.com |
| Sectigo | http://timestamp.sectigo.com |
| GlobalSign | http://timestamp.globalsign.com/tsa/r6advanced1 |
Timestamping ensures signatures remain valid after certificate expires.
signtool verify /pa /v MouseEffects.msix$cert = Get-ChildItem -Path "Cert:\CurrentUser\My\YOUR_THUMBPRINT"
$cert | Format-List *For public distribution, purchase an EV code signing certificate:
| Provider | Approximate Cost |
|---|---|
| DigiCert | $400-500/year |
| Sectigo | $300-400/year |
| GlobalSign | $350-450/year |
Benefits:
- Immediate Windows SmartScreen reputation
- No user prompts about unknown publisher
- Required for kernel-mode drivers
For team environments, store certificates in Azure Key Vault:
# Install Azure SignTool
dotnet tool install -g AzureSignTool
# Sign with Key Vault
AzureSignTool sign `
--azure-key-vault-url "https://yourkeyvault.vault.azure.net" `
--azure-key-vault-client-id "your-client-id" `
--azure-key-vault-client-secret "your-secret" `
--azure-key-vault-certificate "your-cert-name" `
--timestamp-rfc3161 "http://timestamp.digicert.com" `
MouseEffects.msixThe certificate subject must match the manifest publisher:
CN=MouseEffects Dev
<Identity Publisher="CN=MouseEffects Dev" ... />$cert = Get-ChildItem -Path "Cert:\CurrentUser\My\YOUR_THUMBPRINT"
$cert.SubjectThe certificate or its issuer isn't trusted:
# Check certificate chain
certutil -verify -urlfetch MouseEffects-Dev.cerSolution: Install certificate to Trusted Root store.
Package was modified after signing, or certificate doesn't match:
- Verify publisher matches certificate subject
- Re-sign the package
- Check for file corruption
Manifest publisher doesn't match certificate:
# Get certificate subject
(Get-ChildItem "Cert:\CurrentUser\My\$thumbprint").Subject
# Update manifest to matchFor development, create a new certificate:
# New certificate valid for 5 years
New-SelfSignedCertificate ... -NotAfter (Get-Date).AddYears(5)- Never share private keys - Only distribute
.cerfiles (public key) - Use strong key sizes - 2048-bit RSA minimum
- Protect with passwords - Export
.pfxfiles with passwords - Use timestamping - Signatures remain valid after certificate expires
- Store securely - Use Azure Key Vault or HSM for production
- Rotate regularly - Create new certificates before expiration
New-SelfSignedCertificate -Type Custom -Subject "CN=Your Name" `
-KeyUsage DigitalSignature -FriendlyName "Your App" `
-CertStoreLocation "Cert:\CurrentUser\My" `
-TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3","2.5.29.19={text}")Export-Certificate -Cert (Get-Item "Cert:\CurrentUser\My\THUMBPRINT") -FilePath "cert.cer"Import-Certificate -FilePath "cert.cer" -CertStoreLocation "Cert:\LocalMachine\Root"signtool sign /sha1 THUMBPRINT /fd SHA256 package.msix- MSIX Packaging - Create distributable packages
- Building from Source - Build the application