Microsoft’s replacement for the ubiquitous MSI, MSIX, requires the use of code signing certificates to deploy the packages. This is part 2 of a two-part series on MSIX and Certificates. This one is aimed at IT Pros and part 1 was for Developers.
Part 2 Introduction
IT Pros have generally not needed to really deal with code signing certificates. Yes, some (hopefully most) of the software they receive has been signed with a code signing certificate. But usually the vendor used a well-known and trusted Certificate Authority (CA) and their end-user systems automatically trust certificates generated by the CA. So to the average IT Pro, it is something that might be there but they don’t have to deal with it.
But now it is time to learn about code signing because, as someone repackaging software into MSIX packages (and possibly other formats) you are going to need to learn about code signing. There are two things you need to learn about. One is the Code Signing Certificate, but you’ll also need to learn about the Timestamping Service (TSA).
The purpose of a code signing certificate is to assure the recipient that the contents of the package have not been altered since it was created. With MSIX, the person creating the package will digitally sign the package (ideally as part of the package creation) using a code signing certificate.
The timestamping in a certificate is an option that might be present. Like any kind of certificate, code signing certificates have an expiration date. But unlike the case of Server certificates, we can’t easily ask the creator of the package to update the certificate. This is where a timestamp comes in. When TSA is used, the certificate includes an additional timestamp, also issued by the CA. This timestamp verifies that the signing of the package occurred while the certificate used was still valid. So even though the certificate has now expired, you can feel confident it was valid at some point. So as long as the certificate hasn’t been revoked, you should feel comfortable about the safety of the package.
The need to sign MSIX Packages
While it is technically possible to deploy MSIX Packages without code-signing them, you should find the requirements to do so unacceptable. So you will be signing those MSIX packages.
Deploying unsigned packages requires turning a feature called “Developer Mode” on for all client systems. Not only does everyone recommend not doing this, Microsoft doesn’t really document all of the things that turning on this feature does. So let’s just stay with the assumption that you’ll be signing these things. Note: Through the 1903 OS release, you do need to enable “SideLoading” on client systems to deploy MSIX packages (from other than the Microsoft Store). It sounds like Microsoft is looking at making this setting go away soon.
When we start seeing packages from software vendors in MSIX format, these will arrive already signed by them. So as long as you don’t repackage those apps, you don’t need to deal with the code signing. Hopefully, you won’t be repackaging them as much. Instead you would create an add-on (or modification) package that has the settings and data you want to use with the app and deploy the two together.
But anything you repackage into MSIX, whether delivered from the vendor in MSIX, MSI, or EXE form, will need to be signed by you. You only need one certificate, no matter how many packages you sign, so while there is a learning curve and hassle, it really is just a one time hit for you.
Public Cert, Private Cert, or Azure?
You’ll need to pick how things get signed. For most customers, this means acquiring a certificate from a public CA, or creating their own (private) certificate. There is a third option, to let Microsoft sign them for you via Azure, but I don’t expect it to see much use.
A public code signing certificate is one that you purchase from a publicly registered certificate authority. The advantages of using a public CA is that the certificate will already be accepted by default on your end-user systems for installing MSIX packages.
A public CA should also be a TSA, and therefore able to provide the timestamping service. With every CA I am aware of, the timestamping is free and part of the service when you purchase the certificate from them. The CAs require a relatively short expiration on the certificate, typically from 1 to 3 years depending on how much you pay. So the certificates that they offer are quite likely to time out while the app is active in your organization and you will want the timestamping to extend the usable life of the package.
A private code signing certificate is one you generate yourself. The advantage is the zero cost. The disadvantages are that you’ll have to get end-user systems to trust your certificate, and you can’t use timestamping. But you can choose the expiration date yourself. So maybe make it valid for 30 years? The downside to a long expiration period is a slight security one, but as long as you password protect the signing certificate and then protect that password, this is an acceptable risk for most companies.
In the Azure “Device-Guard Signing” case, which is available to insider builds at the time this was written in August 2019, Microsoft offers code signing using the Microsoft Azure Code Signing Service. The service appears to be free (at this time). You need to have an Azure Account, but this can be an Office 365 Account with Azure AD Basic. You will also need to add Microsoft Store for Business or Store for Education, which is free. In essence, the process is the similar to what Microsoft uses for developers submitting to the store. You’d just build your package and upload it to them for signing. Once processed, you would bring it into the Store for Business/Education for distribution to your Azure AD joined clients. That’s a pretty limited use case, as once you want to deliver to non Azure clients you’ll probably have to do your own signing anyway. More information on this service may be found from Microsoft at this link.
Going the Public Cert route
Unless you are a really big distributor of software to other companies, go with a relatively cheap certificate. CAs will offer you different levels of certificates, such as Extended Authentication (EA) certificates. You don’t need those. To issue a certificate, the CA is putting their reputation on the line. With a standard code signing certificate, they will need to perform some minimal checks that you (or your company) is who you say you are. This might be things like looking up public records on your company. The EA level certificate requires much more through verification and will cost a lot more. The value of the EA level code signing cert is really only for software vendors that want to offer downloads from their website.
When you buy the certificate, you should immediately password protect the code signing file. That password must be used whenever code signing is done. This password should be unique and you’ll want to protect who has access to that password. The more people will access to the password, the more people able to potentially generate rogue signed packages that will be automatically trusted by your systems.
Going the Private Cert route
There are at least two ways to generate your own certificate:
- Use Microsoft Active Directory Certificate Services. You first install this as a Role to one domain controller, and then use Servicer Manager to configure the role. Use RSAT Certification Authority (cersrv) to create a template for a Code Signing Certificate with the Subject Name, and finally generate the Code Signing Certificate Request and then export the certificate to a pfx file with a password.
- Run a PowerShell script (see sample below) to generate a self-signed code-signing certificate.
|$Publisher_CN = “CN=Company.MSIX”|
$FolderToExportCert=”$($env:UserProfile)\Documents” #Note: Folder must exist
$CertName=”Company.MSIX” #filename for the cert file
#——————————— Modify lines above only ———————————–
$pwd=ConvertTo-SecureString -String $password -Force -AsPlainText
$PfxName = “$($FolderToExportCert)\$($CertName).pfx”
$cert = New-SelfSignedCertificate -Subject $Publisher_CN -FriendlyName $Publisher_DisplayName -KeyAlgorithm RSA -KeyLength 2048 -Provider “Microsoft Enhanced RSA and AES Cryptographic Provider” -KeyExportPolicy Exportable -KeyUsage DigitalSignature -Type CodeSigningCert -CertStoreLocation “Cert:\LocalMachine\my”
$cert | Export-PfxCertificate -FilePath $PfxName -Password $pwd -Force
If you use the on-prem AD Certificate Services, all of your domain joined machines will automatically accept your packages. If you distribute outside of those machines, someone will need to add the certificate to those systems.
When adding certificates to end-user machines, the certificates must be added to the Computer Certificate Store and into the Trusted root certificates.
The Certificate Details
A code signing certificate is just a certificate includes a string that identifies the certificate type as code signing. The “Subject” field of the code signing certificate is used to identify the “publisher” who is doing the signing. This means your company, but it will be expressed as a string like “CN=TMurgent Technologies”.
It is required that your MSIX packages have a publisher field in the internal manifest file with a matching string or signing will not work.
When packaging in-house software, it makes sense to use your company name for the subject/publisher. When repackaging a software vendors software, I prefer to use this same certificate, and mark the publisher field of the manifest to match the CN= string in the subject of my code signing certificate, but mark the publisher display name to be the name of the software vendor plus an indication that it is re-packaged by my company.
Signed Code and Security
We depend upon the certificate information in signed packages to verify that systems should trust the code. The signed code simplifies our lives, but it brings in new responsibilities. The code signing certificate needs to be password protected, to prevent unauthorized code signing.
When protected by a password, only someone with knowledge of the password can use the code signing certificate to sign a package. But the file might also used without the password to load into certificate stores on end-user machines. This use permits software signed by that certificate to run, but without the password doesn’t permit additional signing.
So you must protect access to that password. Should you loose control over that password to a bad actor, you essentially give them permission to bypass your most basic and pervasive security systems in your company.
Single and Double Signing Options
In smaller companies, single signing is probably the best option. The single option assumes that you have a small number of well trusted individuals that need to sign their packages. The code signing would be something they configure into the tooling that generates the packages so once configured it becomes just an automatic thing that happens.
When you use outside contractors for packaging, you probably shouldn’t be giving them your code signing password. And with larger companies, especially those with heighted concerns over security, it still might make sense to keep the code signing password known by a smaller group, or even one individual. In these cases, double signing is recommended.
With double signing, you use two code signing certificates, one for production and one for test. No matter what the source of the production certificate is from, this test certificate should not be from a public CA or your AD Certificate Authority. Packagers will use this test certificate for package creation, and you don’t need to worry about protecting the password on it. You only add trust for that test certificate on necessary test machines. After testing is completed, the package is then forwarded to an individual that will re-sign the package, using the Microsoft signtool program with the production certificate and password. This second signing will replace the original signing at the package level.
When double signing, make sure both the production and test certificates use the same subject name for the publisher.
Eventually you get your certificate and export it to a pfx file, with a password to protect it.
Ultimately, signing of the package is performed using the Microsoft signtool.exe program. This program is part of the Windows SDK for developers, so you might need to download a small part of the SDK to get it. But in the end, all you need is a copy of the singntool.exe file.
When using the Microsoft MSIX Packaging Tool, you can now configure the tool with your certificate pfx file and password, or the packager can select the file and enter the password each time they package. The MPT will only perform signing of the MSIX package and will ignore internal executable files.
When using Advanced Installer, you can also configure the tool with your certificate pfx file and password, or the packager can select the file and enter the password each time they package. By default, only the MSIX package is signed but there is an option to also sign internal executable (PE) formatted files that are inside the package. If you are thinking long term about things like white listing protection schemes like Windows Defender Application Guard, automatically signing all WinPE files during packaging with the same certificate could be interesting to you. Just keep in mind that if you are using double-signing the internal files won’t be re-signed with the production certificate; so this option might not help you.
Other packaging tools likely work similarly to one of these, but even if you use one that doesn’t offer signing, you can still sign the package yourself using signtool.
Conclusion for Part 2
IT Pros responsible for application packaging will need to learn about code-signing. A process must be put in place to acquire and protect the code signing certificate. Once those are in place, producing signed packages that you can trust should be no more trouble than your current practices.