Digital Signing

One of the main benefits of MSIX is its security-driven architecture. This is provided first by the app container and second, by the fact that each MSIX package carries a digital signature.

Over the last 20 years, no matter the packaging format (a simple zip, MSI, EXE, App-V, etc.), the use of digital signing was always considered an optional procedure by 99% of the packaging teams. This is different now.

Remember! All MSIX packages must be digitally signed. You will see that the OS has a setting called “Developer Mode” that allows for unsigned MSIX packages to be installed - but, this setting is not intended for production use.

Why should you sign an MSIX package?

When deploying an MSIX package, the operating system uses the digital signature to confirm that it can trust the original owner or builder of the package. The digital signature is the standard method to ensure a package was not tampered with.

Digital signing involves attaching a hashed value of the contents of the package file to an “alternate stream” of the file to validate that the file contents have not changed since signing.

Note: When a file is digitally signed, applying the signature is always the last step.

Because the signing process uses the private key from your certificate as a secret for the encryption algorithm, nobody else can alter the file without invalidating the signature. Without your private key (and private key password), no one is able to re-sign the package file with your certificate.

If an attacker gets his hands on the package and adds a malicious file inside, it will break the signature. Without your certificate, the attacker cannot digitally sign the package and the system will automatically reject it.

This forces customers to manage which certificates they will support on their systems, a topic we will discuss shortly.

How to sign an MSIX package?

Generally, applying a digital signature is done by invoking a tool like Signtool.exe from the command line. In its command line, you can specify the files you want to sign, the certificate used for signing, and other configurations.

One important concept to understand is that Signtool reads a field called “Publisher” from the AppXManifest.xml file and compares it to the field called “Subject” in the certificate. The purpose of this comparison isn’t clear, but as we usually package many or all of our packages using the same certificate, this means that we must generate an AppXManifest file to match what is in the certificate.

Traditionally, this is in the form of a string like “CN=Company Name”. Microsoft’s own packages are signed using a certificate with a subject format resembling “CN=Microsoft Windows, O=Microsoft Corporation, L=Redmond, S=Washington, C=US”.

To make this process seamless, packaging tools similar to the Microsoft Packaging Tool and Advanced Installer, and most of the package authoring tools used by developers, provide a helpful GUI that enables package signing. In the end, they all abstract the command line options behind an easy to use GUI to save you time.

Configuring the signing tool is out of the scope of this chapter as this is documented in the user guide of your preferred packaging tool. What you need to understand is where to get your certificate from and how that affects your package. And we'll go into this now.

Where do I get a certificate from?

Windows recognizes certificates if it finds information about them in the system’s certificates manager (certmgr.exe).

You generally have two options to get a certificate to be recognized by the system.

  • You generate a self-signed certificate and pre-deploy it onto the machines where you want to install the application that you will sign. This certificate can be deployed by your IT team to ensure all the machines from your enterprise trust the packages signed with that certificate.

In an enterprise environment this certificate creation and deployment may be controlled through PKI (Private KeyInfrastructure). Sometimes, Group Policy is also used for the distribution.

  • You purchase a code signing certificate from a trusted Certificate Authority (CA) vendor, like Verisign, Comodo, Thawte,etc. Microsoft keeps an up-to-date list of the verified certificate vendors that are pre-deployed within the OS. Purchasing a certificate from one of these vendors guarantees that any Windows OS will see a valid digital signature applied to your package. This is how most software vendors digitally sign their applications (MSIs, EXEs, etc.).

Unless you plan to distribute the package yourself, using a website, it is unlikely that you will need any level of "ExtendedValidation" when getting your certificate from a trusted vendor. So, the most economic option will suffice.

  • You can use the Azure Code Signing Service. Although it is a free service at this moment, you must have some kind of Azuretenant (including Office365) to be able to use it. Your Azure administrator will need to enable the service and instruct you on how to use it. Certificate validation is also provided by Azure, but only in cases when the user is logged in with Azure credentials for your tenant.

How to protect the Certificate with a password

When you get your certificate, you will need to extract the signing format out to a file with a .pfx file extension. When you do this, it is very important to add a password to the file when performing the extraction. This ensures that the .pfx file cannot be used to sign any files without providing the required password.

The password itself should be kept safely; available only to those that need it and can be trusted. For example, you would typically not give the password to a third party packaging company that you work with. Instead, you should use a cross-signing technique to allow them to sign the package using an untrusted certificate, so that you can later re-sign it with a trusted one.

Certificate Timestamps

As you can probably imagine, certificates expire. While you can control the expiration date of certificates that you privately generate, those purchased from a public CA (Certificate Authorities) have a short life-span - typically ranging from 1 to 3 years, depending on the price.

Important! If you don't add a timestamp during the signing process, the package will be considered invalid when the certificate expires. This expiration would prevent any new installations of the package, although it shouldn't affect end-users that already have the package installed.

To prevent this, Signtool supports adding a timestamp to the signature. This involves having Signtool communicate with a public CA timestamp authority to validate the actual time of the signature, and storing that information in the file alternate stream with the certificate information.

This validates that the file contents have not changed since you signed it, and that the signing occurred while the certificate was still valid. This process requires the trust of a CA providing that timestamp, preventing you from just turning the clock back on the machine used to perform the signing.

With the timestamp applied, the package can be installed even after the certificate expires.

Currently, all public CAs that we have reviewed support using their timestamping service (although usually they include a warning about preventing Denial of Service attacks if you try signing too often).

A common reference used is:

Some other vendors will add “/rfc3161” to the end of their URL.