Skip to main content

Digital Signature

A digitalSignature block tells MPDEV to sign the produced packages and (almost) every executable file inside them. Signing is mandatory for production: Windows SmartScreen, MSIX install, the MSI updater, and the MSI contextMenu capability all require it.

Set digitalSignature in the common section to sign both MSI and MSIX, or inside msi / msix to sign just one output.


Three signing methods

The digitalSignature object is a oneOf of three shapes, distinguished by signWith:

signWith valueWhen to use itType definition
"AzureTrustedSigning"Recommended for production. Cloud signing with Microsoft's Trusted Signing service. No local cert handling.AzureTrustedSigningSignature
"Thumbprint"You have a local cert with a private key in the Personal store.ThumbprintSignature
"GenerateTestCertificate"Local development / CI tests only. MPDEV creates a fresh self-signed cert. Never ship to users.TestCertificateSignature

What gets signed

When digitalSignature is set, MPDEV automatically signs the produced installer and every file inside it whose extension is in this list:

.cab, .cat, .com, .dll, .exe, .js, .jse, .msi, .msp, .ocx, .ps1, .ps1xml, .psm1, .sys, .vbs, .vbe, .wsf

Already-signed files are not re-signed. Use exclusions to opt out of files that you specifically don't want signed.

"digitalSignature": {
"signWith": "AzureTrustedSigning",
,
"exclusions": [
"source\\\\third-party\\\\already-signed\\.dll$",
"source\\\\external\\\\.+"
]
}

exclusions are regex patterns matched against file paths. Validation: valid regex.


1. Azure Trusted Signing

The modern, cert-less way to sign code. Microsoft hosts the certificate, you authenticate with an Azure identity, your installer is signed in the cloud.

"digitalSignature": {
"signWith": "AzureTrustedSigning",
"endpoint": "https://eus.codesigning.azure.net",
"codeSigningAccountName": "MySigningAccount",
"certificateProfileName": "MyProductionProfile",
"timestampServer": "http://timestamp.acs.microsoft.com",
"correlationId": "ci-build-12345",
"credentials": ["EnvironmentCredential", "AzureCliCredential"],
"exclusions": []
}

Properties

PropertyTypeRequiredDefaultDescription
signWithconstyesMust be "AzureTrustedSigning".
endpointURLyesThe regional Trusted Signing endpoint, e.g., https://eus.codesigning.azure.net.
codeSigningAccountNamestringyesYour Trusted Signing account name.
certificateProfileNamestringyesThe certificate profile name within the account.
timestampServerURLyesRFC 3161 timestamp server. Trusted Signing certs are 3-day valid – timestamping is mandatory. Recommended: http://timestamp.acs.microsoft.com.
correlationIdstringnoFree-form ID to correlate sign requests in your build logs (e.g., CI build number).
credentialsenum[]no["EnvironmentCredential"]Authentication methods tried in order.
exclusionsstring[] (regex)noFiles to skip during file signing.

Authentication

credentials is an array of credential types from Azure's DefaultAzureCredential chain. MPDEV tries them in order and uses the first one that works.

CredentialHow it authenticates
EnvironmentCredential (default)Reads AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET env vars. The standard CI option.
ManagedIdentityCredentialUses the VM/container's managed identity.
WorkloadIdentityCredentialFederated workload identity (e.g., GitHub Actions OIDC).
SharedTokenCacheCredentialReuses tokens from the shared token cache.
VisualStudioCredentialThe signed-in Visual Studio account.
AzureCliCredentialThe currently logged-in az user.
AzurePowerShellCredentialThe currently logged-in Connect-AzAccount user.
AzureDeveloperCliCredentialThe currently logged-in azd user.
InteractiveBrowserCredentialPops up a browser sign-in. Last-resort for desktop dev. Useful for manual testing.

For CI/CD set the three env vars and do not specify the credentials property:

AZURE_TENANT_ID=...
AZURE_CLIENT_ID=...
AZURE_CLIENT_SECRET=...

Validation

The valid-azure-trusted-signing validator runs at build time and verifies that MPDEV can connect successfully to the Trusted Signing endpoint with the chosen credential chain. If your secrets are wrong, the build fails fast.

Rate limits: Trusted Signing has per-account rate limits. Throttle parallel CI jobs if you hit 429 responses.


2. Local thumbprint

Use a certificate that is already imported into the Personal certificate store of the build account, identified by its thumbprint.

"digitalSignature": {
"signWith": "Thumbprint",
"thumbprint": "1A2B3C4D5E6F7081A2B3C4D5E6F708192A3B4C5D",
"timestampServer": "http://timestamp.sectigo.com",
"exclusions": []
}

Properties

PropertyTypeRequiredDescription
signWithconstyesMust be "Thumbprint".
thumbprintstringyes40-character hex thumbprint (case insensitive) of an active certificate with a private key in the Personal store.
timestampServerURLyesRFC 3161 timestamp server.
exclusionsstring[] (regex)noFiles to skip during file signing.

Finding the thumbprint

  1. Open certmgr.msc.
  2. Navigate to Personal → Certificates.
  3. Double-click your code signing cert.
  4. Details tab → Thumbprint field. Copy the value, strip spaces.

Or via PowerShell:

Get-ChildItem -Path Cert:\CurrentUser\My | Format-List Subject, Thumbprint

Common timestamp servers

  • http://timestamp.acs.microsoft.com (Trusted Signing public TSA)
  • http://timestamp.sectigo.com
  • http://timestamp.comodoca.com
  • http://timestamp.digicert.com

Validation

  • valid thumbprint – verifies the thumbprint matches a real, active cert with a private key in the Personal store.
  • valid timestamp server – verifies the URL responds with HTTP 200.

3. Generate test certificate

For local development and CI smoke tests only. MPDEV creates a brand new self-signed certificate per build, signs everything with it, and you import it manually into the Trusted Root Certification Authorities store on test machines.

"digitalSignature": {
"signWith": "GenerateTestCertificate",
"timestampServer": "http://timestamp.sectigo.com"
}

Properties

PropertyTypeRequiredDescription
signWithconstyesMust be "GenerateTestCertificate".
timestampServerURLyesRFC 3161 timestamp server.
exclusionsstring[] (regex)noFiles to skip during file signing.

The certificate's password is empty. It is dumped to a .pfx file in the build output for you to import on test machines. Never use this in production – Windows will not trust the cert without a manual import to Trusted Root.


Per-output signing

You can sign just one output by placing digitalSignature inside msi or msix:

{
"msi": {
"digitalSignature": {
"signWith": "Thumbprint",
"thumbprint": "…",
"timestampServer": "http://timestamp.sectigo.com"
}
},
"msix": {
"digitalSignature": {
"signWith": "GenerateTestCertificate",
"timestampServer": "http://timestamp.sectigo.com"
}
}
}

In the example above the MSI is signed by your real certificate and the MSIX is signed by an ephemeral test cert.


Capabilities that REQUIRE a digital signature

FeatureWhy
MSIX builds (any)Windows refuses to install unsigned MSIX packages. (Test certs only after the cert is trusted on the install machine.)
msi.contextMenuImplemented as a sparse MSIX overlay that needs identity, hence a signature.
msi.updaterThe updater compares the new installer's signature against the installed one. Without digitalSignature there is nothing to compare. installDir must be under %ProgramFiles%.

The corresponding validators are digital signature required - context menu and digital signature required - updater.

MSIX publisher must match the cert subject. When signing an MSIX with a real cert (Thumbprint or Trusted Signing), the certificate's Subject DN overrides $.publisher for MSIX identity – they must match for a successful install.