DVLUP
March 15, 2025

Trusted Signing

Posted on March 15, 2025  •  5 minutes  • 1041 words
Table of contents

Say goodbye to managing PFX files and problems code signing your apps. Over the past year or so, I’ve been working with Microsoft to test a service that lets you sign your code using an HSM-backed private key. This means your identity is verified by Microsoft, and you can sign all your stuff with a simple API call!

Azure Trusted Signing

I have a real-world app where I code sign the app and appinstaller automatically. I walk you through how that is done so you can copy it, but first I should step back and explain what the service is.

Trusted Signing : Protect your applications with certificates that are fully managed through certificate authorities that are part of the Microsoft Trusted Root Certificate program and meet WebTrust certification criteria.

You don’t need to handle the certificate generation side of things, just validate you/your company’s idenity with Microsoft when you set up your account. To get started, go to Trusted Signing - Quickstart and set up your account.

What is important to distinguish is you can get an account for an organization or an individual. I strongly recommend that you read through that doc in its entirety before performing any actions. I have done this for both organization (Lancelot Software, LLC) and an account for me personally (Lance McCarthy).

You use your company’s legal identification if signing up for organization, or you use your personal documents (driver’s license, passport, etc), see the Create an Identity Validation Request section for more details.

Once you have a Trusted Signing account ready, you can start signing code! The docs have plenty of examples:

In Practice

Today, I will show you how to use the GitHub Actions as part of an automatic publishing workflow.

The Project

First, go to my XkcdViewer repo and see the .NET MAUI project in src/XkcdViewer.Maui . If I want to distribute the app outside of the Microsoft Store, say to folks via a GitHub Release, then I need to compile & package the app as a signed MSIX package.

This is the perfect use-case for signing my MSIX with Trusted Signing!

The Workflow - Producing an MSIX

Okay, now let’s look at my GitHub Actions workflows. I have two of them:

In the Release workflow, there are two Windows-specific jobs:

The “store” build is specifically to build an msixupload package for submitting to the Microsoft Store. The app manifest uses my Store identity (on line 150 ) and does not need to be signed by me… this is because Microsoft will sign it after submission approval.

However, the “sideload” build is going to produce an MSIX that users can download from GitHub install directly. This one needs to be signed, and is what we will use Trusted Signing for. I need to change the app manifest to use the same identity that was verified by Trusted Signing, you will see that happen on Line 86 .

Signing Time

Typically you might jump right into the signing step right after building the MSIX, but I have a final job that creates a gitHub Release and attaches the artifacts. I decided to put the signing step there, just before I attach the MSIX to a release.

Regardless of where you using it, you need to first sign into the Azure CLI. The advantage of doing this in GitHub is that you can use ODIC credentials and you do not need to have any secrets in the workflow. See the instructions here => Azure Login with OIDC ;

At the workflow or job level, you allow permission to use the GitHub JWT token to authenticate with Azure

# in the workflow, 
permissions:
  id-token: write
  contents: read

Later when you use azure/login@v2, you do not need a client secret! GitHub only needs the service principal’s Client ID, Tenant ID, and Subscription ID. Note that these are not secret values, though it usually good practice to obsfucate them:

    - name: Azure login using OIDC via GitHub
      uses: azure/login@v2
      id: azlogin
      with:
        client-id: "32..........................d"
        tenant-id: "bd..........................a"
        subscription-id: "4............................7"

Okay, now that you are signed into the Azure CLI, you can use azure/trusted-signing-action. Here is my entire step:

    - name: Sign files with Trusted Signing
      uses: azure/trusted-signing-action@v0.4.0
      with:
        endpoint: https://eus.codesigning.azure.net/
        trusted-signing-account-name: PrimaryCodeSign
        certificate-profile-name: lancemccarthylivepublic
        timestamp-rfc3161: http://timestamp.acs.microsoft.com
        timestamp-digest: SHA256
        file-digest: SHA256
        files-folder: ${{github.workspace}}
        files-folder-filter: msix
        files-folder-depth: 3
        exclude-azure-cli-credential: false
        exclude-environment-credential: true
        exclude-workload-identity-credential: true
        exclude-managed-identity-credential: true
        exclude-shared-token-cache-credential: true
        exclude-visual-studio-credential: true
        exclude-visual-studio-code-credential: true
        exclude-azure-powershell-credential: true
        exclude-azure-developer-cli-credential: true
        exclude-interactive-browser-credential: true

Notice these specific settings I use:

Conclusion

Since I wanted to create an actual release on my GitHub Releases page, I use softprops/action-gh-release to create a release and attach both the signed and Store artifacts.

    - name: Release
      uses: softprops/action-gh-release@v2
      with:
        name: "XkcdViewer v${{needs.shared-resources.outputs.app_version}}"
        files: ${{github.workspace}}/**/*
        ...

See the result for yourself => XkcdViewer/releases/tag/v2025.303.80.0 .

The msixupload file is only for uploading to the Store for update submission, but the two msix file attachments are signed by Trusted Signing and can be installed directly!

If I download the appropriate msix file and look at Properties > Digital Signatures > cert details, I see the expected result:

Most importantly, if I run the msix, Windows trusts the certificate and the app can be installed!

I hope this helps motivate you as much as it did for me. I’ve spent many years dealing with cert managament, renewal, and special techniques to use and protect the PFX. This feels like code signing certificates have the same easy of use as SSL certificates do now and is a welcome change

Follow me on your preferred social network =>