How to Sign a UWP Application with a Digital Certificate

All development teams should get in the habit of digitally signing their applications, especially before sending to QA or production. Code signing is not only a best practice. It also takes a load off of a security team when vetting packages and upgrades. Using Visual Studio makes it easy to sign a UWP application with a self-signed digital certificate. However, outside of Visual Studio it becomes very difficult. And there is almost no documentation on creating a CA-signed certificate for UWP applications.

Watch the Video on YouTube

If you would rather follow along with a video, you can catch a video of this post on my YouTube channel.

How to Sign a UWP Application with a Self-Signed Certificate Using Visual Studio

Before we dive into the command line, let’s discuss how to perform this operation in Visual Studio. Let’s create a new UWP project that we can use for testing purposes. This will be explicitly for side-loading. We won’t be involving the Microsoft store.

Creating a New UWP Project

Open Visual Studio and create a new project based upon the Blank App (Universal Windows) project template. Feel free to target any version of Windows 10, as this is for demonstrative purposes.

Once you have created the project, open the Package.appxmanifest file and navigate to the Packaging tab.

Click the Choose Certificate… button. Click the Create… button. Specify your name, and supply a password to protect the certificate. Click the OK button. Your new certificate details will be loaded into the Choose a Certificate dialog. Click OK to dismiss the dialog and apply the certificate to your package settings.

Verifying the Signature

We can verify that the certificate works by publishing the application. Right click the project in the Solution Explorer, choose Publish | Create App Packages… We’re going to use the default distribution method. Leave the default selected to use the certificate that we just created. We won’t be worrying about a Timestamp server for this demonstration. On the next screen, I’m choosing to simplify things by only generating packages for the x64 architecture. You do you.

For the installer location, I chose to create a directory named “publish” under my solution’s directory. This option won’t matter much, as the package will be generated in a different location. Click the Create button to continue. Once the solution builds, you can easily access the output location from the dialog that appears.

Open the output location and navigate to the versioned folder. Right click on the .msixbundle file and choose Properties. Activate the Digital Signatures tab and you can see that the package is digitally signed with the certificate that we created.

How to Sign a UWP Application with a Self-Signed Certificate Using PowerShell

We want to move in the direction of signing our UWP apps with a certificate signed by a CA. In order to do this, we need to understand the certificate requirements of a UWP application. There is no better way to explain this than by creating a self-signed certificate manually using PowerShell.

We’ll use the New-SelfSignedCertificate cmdlet to generate the certificate. Open up a new PowerShell command prompt and type the following:

Since we are targeting the current user’s personal certificate store, you do not need elevated privileges to perform this action.

New-SelfSignedCertificate `
    -Type Custom `
    -KeyUsage DigitalSignature `
    -CertStoreLocation "Cert:\CurrentUser\My" `
    -Subject "CN=Test UWP Certificate" `
    -TextExtension @( `
        "2.5.29.37={text}1.3.6.1.5.5.7.3.3,1.3.6.1.4.1.311.84.3.1", `
        "2.5.29.19={text}false")

Let’s talk about what this command line does:

  • The -Type argument indicates that we’re going to be creating a custom type of certificate. This is important, because a standard CodeSigningCert certificate will not work for UWP applications.
  • The -KeyUsage argument indicates that we’re going to be using this certificate for digital signatures. Duh!
  • The -CertStoreLocation argument indicates that we’re going to be storing the certificate under the current user’s personal certificates store. This is important as this is the location Visual Studio looks for UWP certificates to use for signing.
  • The -Subject argument indicates the common name value that we desire. The value specified above will cause the “Issued To” field to show “Test UWP Certificate” in the Certificates MMC snap-in. You can choose a different value here, if you so desire.
  • The -TextExtension argument is the bread and butter of this command line. Let’s dive into these values next.

Specifying Basic Usage and Extended Key Usage via -TextExtension

The -TextExtension argument allows us to specify the Basic and Extended Key Usage for the certificate. We essentially need the certificate to indicate the following:

  • This is an end-entity certificate. In other words, this certificate is the leaf in the chain and will not be used for signing other certificates.
  • This certificate is used for code signing. The OID for code signing is 1.3.6.1.5.5.7.3.3. This is a well-documented OID.
  • This certificate is used for UWP code signing. The OID for UWP signing is 1.3.6.1.4.1.311.84.3.1. This is an undocumented Microsoft-specific OID.

If your basic or extended key usage does not contain this information, then neither Visual Studio nor signtool.exe will be able to sign your UWP package.

The text “2.5.29.37={text}1.3.6.1.5.5.7.3.3,1.3.6.1.4.1.311.84.3.1” indicates that the code signing and UWP code signing OIDs need to be included in the extended key usage. The text “2.5.29.19={text}false” indicates that this is an end-entity certificate.

We can now view the certificate in the certificates snap-in in MMC.

To open MMC, type ‘mmc’ into a command prompt. In MMC, click the File menu and choose “Add/Remove Snap-in…” Choose Certificates and click the Add button. Choose My user account and click Finish. Then Click OK to close the dialog.

Double-clicking the certificate under Personal | Certificates will show the certificate information. Choose the Details tab and you can indeed verify that the basic and extended info were set correctly.

Signing our UWP Application with our New Self-Signed Certificate

Back in Visual Studio, open the Package.appxmanifest file again and go back to the Packaging Tab. Click Choose Certificate… and Select from store…

Chances are, the Select a Certificate dialog will open with the certificate you created in the first section of this post. That’s fine. Click the More choices link to show a list of all certificates you can sign with. Select the certificate that you just created and click the OK command button. Click OK to dismiss the Choose a Certificate dialog.

Once we publish again, we can see that the new certificate was indeed used.

Creating a UWP Signing Certificate Enrollment Policy

If you are developing for an enterprise, you’ll want to be able to sign your apps with digital certificates signed by your CA. The easiest way to accomplish this is via an Active Directory Certificate Enrollment Policy.

If you are a developer, you most likely will not have the privileges to accomplish these steps. You’ll need to contact your network administrator to do so. I’m also not going to go into the process of installing and configuring Active Directory Certificate Services here.

Launch the Certification Authority Snap-in. Under your CA, right-click Certificate Templates and select Manage. Right-click Code Signing and choose Duplicate Template.

Setting General and Compatibility Information

On the Compatibility tab, change the Certificate Authority and Certificate Recipient to Windows Server 2016.

On the General tab, change the Template Display Name to “UWP Code Signing”. The Template Name should update automatically.

Configuring the Extended Key Usage Policies

On the Extensions tab, select Application Policies and click Edit. Click the Add… button to add a new Extended Key Usage policy.

Because Microsoft has not documented the UWP Code Signing OID, you’ll have to create a new policy. Click New… and in the New Application Policy add the following:

Name: UWP Code Signing
Object identifier: 1.3.6.1.4.1.311.84.3.1

Click OK. Make sure the new policy is selected in the Add Application Policy dialog and click OK again. Check the Make this extension critical checkbox. Click OK to dismiss the dialog.

Configuring the Basic Constraints

Next select Basic Constraints and click Edit. Enable the extension and check the option to make it critical.

Restricting Enrollment

Activate the Security Tab. The targeted audience must be granted the ability to Read and Enroll. For simplicity purposes, I’m going to allow Authenticated Users the ability to Enroll.

I advise against this in a production environment. Ideally, you will choose to add a domain group to this list and grant privileges at that level.

Click the OK button to commit the changes and close the dialog.

Back in the Certification Authority Snap-in, right-click Certificate Templates and click New | Certificate Template to Issue. Find the UWP Code Signing template we just created, select it and click OK. The template will be added to the list.

Requesting a New UWP Signing Certificate

In the MMC Certificates snap-in (see above for directions how to launch this), navigate to the current user’s Personal Certificates store. In the Actions panel, choose More Actions | Request New Certificate…

If you were already logged in, you will most likely need to reboot before the enrollment certificate changes will take effect. I have found that invoking gpupdate /force does not work in this scenario. If you find a solution to this problem, please leave a comment below.

Choose Next to continue. Ensure that the Active Directory Enrollment Policy option is highlighted and click Next. Select the UWP Signing Certificate Enrollment Policy that was created in the previous step. Then click the Enroll button.

Windows will create a new UWP Signing certificate for you and place it in the Personal Certificates store. You can then follow the previously outlined steps to sign the UWP package.

How to Sign a UWP Application with SignTool.exe

Once you have a real certificate, it will be beneficial to know how to digitally sign the UWP package using signtool.exe so that you can plug this process into your CI/CD pipeline. The easiest way to accomplish this in an unambiguous fashion is to utilize the certificate’s thumbprint. You can find the thumbprint on the Details tab of the Certificate dialog under the field “Thumbprint” (again, see above for information on how to get there).

Open a PowerShell command prompt and type the following:

Note that the path to your signtool.exe executable may be different than mine. See this post for more information on how to find it.

& 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64\signtool.exe' `
    sign `
    /fd SHA256 `
    /sha1 <thumbprint> `
    <path-to-msixbundle>

These options do the following:

  • sign – informs signtool that we will be signing a binary.
  • /fd – Chooses SHA-256 as the file digest algorithm. This is important and required by UWP applications.
  • /sha1 – Indicates the thumbprint of the signing certificate. This is important for disambiguation, especially in a CI/CD pipeline where multiple signing certificates could be installed.

Leave a Reply