Self-Signed Code Signing Certificates for MSIX: A Practical Guide
2026-06-02
Tags: Windows · Microsoft Store · MSIX · Store Pitfalls
In the previous article, we walked through the full pre-submission MSIX testing workflow. One step that came up repeatedly was dealing with self-signed certificates — installing them into the Trusted People store, packaging with the right certificate, and so on. But that article glossed over an important question: how do you actually create one?
This guide covers everything you need to know about self-signed code signing certificates for MSIX packaging: creating them, exporting them, using them in Visual Studio, and managing them across your team.
Why MSIX Needs Signing
MSIX packages must be digitally signed before they can be installed. This is not optional — even for sideloading and local testing, the operating system requires a valid signature on every .msix file.
For Store distribution, Microsoft signs your package with their own certificate after certification. But for local testing and sideloading, you need a certificate of your own. This is where self-signed certificates come in: they let you sign packages for development and testing without purchasing a commercial code signing certificate.
The signing process serves two purposes:
- Integrity: Ensures the package hasn't been tampered with after signing
- Identity: Identifies the publisher (you) — the CN (Common Name) in the certificate must match the
<Publisher>value in yourPackage.appxmanifest
Using New-SelfSignedCertificate
Windows includes the New-SelfSignedCertificate PowerShell cmdlet, which can generate certificates for testing purposes. Open PowerShell as Administrator and try this:
New-SelfSignedCertificate -Type Custom -Subject "CN=YourCompany" -KeyUsage DigitalSignature -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}") -CertStoreLocation "Cert:\CurrentUser\My"Let's break down each parameter:
| Parameter | What it does |
|---|---|
-Type Custom | Creates a custom certificate rather than a basic one |
-Subject "CN=YourCompany" | Sets the Common Name — this should match your app's Publisher in Package.appxmanifest |
-KeyUsage DigitalSignature | Marks the certificate for digital signature use |
-TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}") | Extended Key Usage set to Code Signing (1.3.6.1.5.5.7.3.3), plus Basic Constraints set to End Entity (2.5.29.19) — required by the Windows deployment engine for app packages |
-CertStoreLocation "Cert:\CurrentUser\My" | Stores the certificate in the current user's Personal store |
Without both TextExtension values, the certificate may not be fully recognized — the Basic Constraints OID marks it as an End Entity (not a CA), which the Windows deployment engine checks when verifying MSIX packages. Missing it can cause deployment errors or WACK warnings on certain Windows builds.
Note: In my own projects, I've been using self-signed certificates without the Basic Constraints extension and they've worked without issues. The constraint is a recommended best practice from Microsoft, but not strictly required for development and sideloading scenarios.
Creating the Certificate with Code Signing EKU
If you already created a certificate without the Code Signing EKU, you can still verify whether it has the right properties. Open the certificate (via certlm.msc) and check Details → Enhanced Key Usage — you should see Code Signing listed.
Here's a practical script that creates a certificate and prepares it for MSIX use:
# Create a self-signed code signing certificate (Code Signing EKU + Basic Constraints)
$cert = New-SelfSignedCertificate -Type Custom -Subject "CN=YourCompany" -KeyUsage DigitalSignature -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}") -CertStoreLocation "Cert:\CurrentUser\My"
# Display the certificate details
$cert | Format-List Subject, Thumbprint, NotAfter
# Output the thumbprint for easy reference
Write-Host "Certificate thumbprint: $($cert.Thumbprint)"Replace "CN=YourCompany" with your actual publisher name. You can find your publisher name in Package.appxmanifest under the Identity element:
<Identity Name="YourApp" Publisher="CN=YourCompany" Version="1.0.0.0" />Exporting PFX vs CER
After creating the certificate, you'll typically need two types of files:
PFX (Personal Information Exchange)
Contains the private key + certificate. This is what Visual Studio uses to sign packages. Treat it like a password — anyone with access to the PFX can sign packages as you.
$password = ConvertTo-SecureString -String "YourPassword" -Force -AsPlainText
Export-PfxCertificate -Cert $cert -FilePath "codesign.pfx" -Password $passwordCER (Certificate file)
Contains only the public certificate (no private key). This is what you distribute to test machines so they can trust your signed packages.
Export-Certificate -Cert $cert -FilePath "codesign.cer"Quick reference
| Format | Contains Private Key? | Usage |
|---|---|---|
.pfx | Yes | Signing packages (Visual Studio, signtool) |
.cer | No | Installing on test machines to establish trust |
Importing the Certificate and Checking the Thumbprint
To install MSIX packages signed with your self-signed certificate on a test machine, the certificate must be trusted by the system.
Install the certificate
- Double-click the
.cerfile → Install Certificate - Select Local Machine → Browse → select Trusted People
- Complete the wizard
Alternatively, via PowerShell:
Import-Certificate -FilePath "codesign.cer" -CertStoreLocation "Cert:\LocalMachine\TrustedPeople"Find the thumbprint
You'll need the thumbprint when using command-line signing tools:
# List all code signing certificates in your personal store
Get-ChildItem -Path "Cert:\CurrentUser\My" -CodeSigningCert | Format-Table Subject, Thumbprint, NotAfterThe thumbprint is a 40-character hexadecimal string. Copy it exactly — you'll need it for signing commands.
Using the Certificate in Visual Studio
Once you have a PFX file, you can use it in Visual Studio's packaging wizard:
- Right-click your project → Package and Publish → create a new packaging profile
- At the Select Signing Certificate step, click Select from File...
- Browse to your
.pfxfile and enter the password - Complete the packaging wizard
The certificate is saved in the packaging profile, so you don't need to re-select it every time. However, if the certificate expires or you switch to a new one, you'll need to update the profile.
Using the certificate from the certificate store
If you imported the PFX into your personal certificate store, you can also select it directly:
- At the signing step, expand the dropdown instead of clicking "Select from File..."
- Look for your certificate in the list (identified by the CN you specified)
- Select it and proceed
This approach is convenient but be careful — Visual Studio may cache a specific thumbprint, and if the certificate is renewed (new key pair), the stored reference may become invalid.
Certificate Expiration, Renewal, and Re-Signing
Self-signed certificates created with New-SelfSignedCertificate default to 1 year of validity (some versions default to 3 years — check the NotAfter property).
Checklist
- [ ] Note the expiration date of your certificate
- [ ] Before expiration, create a new certificate and re-sign all packages
- [ ] Distribute the new
.certo test machines - [ ] Update the packaging profile in Visual Studio
- [ ] For Store submissions, generate a new Test package with the new certificate
To check expiration:
Get-ChildItem -Path "Cert:\CurrentUser\My" -CodeSigningCert | Format-Table Subject, NotAfterWhen you renew, create a new certificate with the same CN, export the new PFX/CER, and re-sign your packages. The thumbprint will change, so make sure all references are updated.
Tips for Team Development
When multiple developers need to sign packages with the same certificate:
- Store the PFX in a secure, shared location — a password-protected archive in team storage or a password manager that supports file attachments
- Never commit the PFX to source control — add
*.pfxto your.gitignore - Document the password in your team's password manager, not in code or docs
- Each developer imports the PFX into their personal certificate store, then selects it from Visual Studio
- Use the same CN across all certificates if you need to create per-developer certificates (for non-shipping builds)
For CI/CD pipelines, most build agents support importing a PFX via secure environment variables or secrets — check your CI platform's documentation for the recommended approach.
This article is supplementary reading for the Store Pitfalls series.