Selling Trust, Part 3
Code signing for Windows is starting to get personal. This marks the third time I am writing about the issues surrounding Microsoft Windows code signing certificates, and it does not appear as if this hassle will stop anytime soon. I first wrote about the mess that is code signing on Windows five years ago in a blog post titled “Selling Trust.” Back then, I complained that ensuring the safety of users on any computers should not be expensive, and that the trust industry that has emerged around verifying who made some software resembles a giant pyramid scheme.
The second part of this odyssey has not been published here on the Zettlr blog. Rather, it forms the backstory I prepended to a guide on how to use Azure Trusted Signing. You can read that second part here. To summarize this article: In 2024, Microsoft upped the requirements for code signing for Windows by requiring not just certificates derived from a trusted root certificate, but also that these certificates are stored on FIPS-compliant, secure storage. You may have already heard of this in the form of YubiKey. As a result, I switched to Azure for signing Zettlr’s releases, because third-party companies used this new requirement as a pretense for ramping up their prices. Instead of paying $500 for a certificate valid for one year, you’ll now have to pay $500 for a certificate, plus an additional $50 per month just to store that certificate in a way to make Microsoft happy (these are just example prices I took from my previous certificate provider). I did some quick napkin calculation last year to determine that signing Zettlr for Windows would run me more than $1,000 a year. Just for a 10kb text file.
Now, Microsoft has moved the goalposts again, and this is the cause for this third blog post in this series.
Background: Code Signing Certificates
Just as a quick refresher: Code signing describes a process by which some software developer signs a program they created. The process ensures that anyone on the internet who downloads this program can see who made it. If a software developer doesn’t sign their program, Windows would refuse to run it. Because anyone, including your dog, could create software and thereby put malware out into the wild. And we don’t want this.
So, in short, by signing a program using a code signing certificate, you essentially provide (technical) proof that you created this program. Doing so raises the bar for malicious actors who may want to distribute malware. To be sure: Malicious developers could also just pay for a certificate, and distribute code-signed malware using it. However, due to the fact that there’s a legal person associated with the certificate, it is easy to find out who signed the app, and revoke that certificate. Then it’s the same as if the software had never been code-signed.
All in all, code-signing is not a bullet-proof, but a relatively sufficient way to ensure that what users – especially non-technical – install on their systems is probably safe.
I personally have changed my stance on code-signing since I published the first article. Back then, I was very skeptical. I didn’t want to provide my identity to some third-party data vendor, and I believe the recent fall-out from the UK Age Verification legislation shows that my gut feeling was not wrong. What I also strongly opposed back then was the high cost associated with it.
But two things have changed. First, I do believe that developers of software that (in the case of Zettlr) hundreds of thousands use every day do have a special responsibility towards keeping their users safe in the digital realm. And second, I do believe that a modest price-tag might be justified to providing the infrastructure that keeps software safe.
What hasn’t changed, however, is my opposition to how code signing is handled by Microsoft.
How Code Signing Should Work
Before diving into the critique I have towards Microsoft, and explaining what is wrong with their approach to code signing, let me first talk about a prime example of how I believe code signing should work: Apple.
A short time after I started developing Zettlr, I bought code signing certificates from both Apple and Microsoft. For Apple, this process was straight forward: Sign up for their developer program, pay about $100 a year (or less than $9 a month), and get your code signing certificate. And that’s it.
Since 2020, I have not had a single issue with this process. The code signing certificate works out of the box, it is trivial to get it, relatively straight-forward to implement (of course, with some technical knowledge), and it just works. I had to exchange it once because even Apple certificates expire, but again, this was a trivial amount of work.
There are other issues with Apple, but these are extremely minor, and simple to fix when they occur. All in all, the experience of ensuring that Macs don’t complain about my software is as frictionless as it could possibly get.
How Microsoft Threatens Their Own User’s Safety
With this positive example out of the way, let’s move on to a critique of the way Microsoft approaches code signing. Specifically, I have three points to make:
- Microsoft sets requirements for software developers without explaining how to fulfill them.
- Microsoft constantly moves goalposts.
- Certificate Providers see selling certificates as a way to turn a profit.
1. Microsoft Sets Requirements for Software Developers Without Explaining How to Fulfill Them
The most egregious fact of Windows code signing is that Microsoft has a laundry list of demands towards developers, but refuses to explain how to satisfy them. Remember the “Developers! Developers! Developers!” chant by Steve Ballmer decades ago? Ballmer’s intention with this chant was allegedly to make Microsoft realize that they need to do better to developers. Well, this blog post is one hint for how well this went.
Indeed, Microsoft is very clear in that you must code-sign your program if you develop software. Otherwise, Windows won’t run it. But what Microsoft is very opaque about is how to code-sign your program. You will find that you need to use a small program called “SignTool” for that, and you need a certificate. But where should you get that certificate? Well, good luck finding out.
There is an implication that some of the providers of code signing certificates out there would be trusted by Microsoft. But Microsoft never really clearly explicates which companies are authorized to sell code signing certificates that work for Windows. So us developers are on our own when it comes to performing code signing.
A simple search on the web will unearth dozens of Reddit or Stack Overflow posts of developers complaining that they don’t understand how code-signing works. To be fair: everyone I know has at some point been able to implement code-signing. But I do believe that it is Microsoft’s responsibility to make this process straight-forward. You raise demands? Then you provide a way to fulfill them.
Apple shows how it should be done. They say that developers have to code-sign their apps, and they in fact provide a way to fulfill this requirement. Microsoft, on the other hand, only makes demands, but doesn’t help fulfill them.
Fortunately, this has changed when they introduced Azure Trusted Signing. With Azure Trusted Signing, there was finally a way for developers to perform code-signing of their apps provided by Microsoft directly. No more guessing whether some certificate company was trustworthy. Microsoft makes demands, and Microsoft provides a solution for them. Successfully setting up code signing was an odyssey on its own, but at least it was a first-party solution.
2. Microsoft Constantly Moves Goal Posts
However, it wouldn’t be Microsoft if it “simply worked.” Indeed, now that Microsoft finally provides a first-party solution to code signing, developers now have to fight a second snake: Microsoft has a tendency to move goalposts around at will.
When I signed up for Microsoft Code Signing in early 2025, it worked (relatively) flawless. Back then, I knew that I would have to renew my identity validation once a year, and that time is right now. So, a few weeks ago, I logged in to the Azure Portal … just to find out that I am no longer eligible to perform code signing.
What has happened is that shortly after I signed up for Azure Trusted Signing, Microsoft has, in its infinite wisdom, decided to stop the onboarding of individual developers from outside of North America. They indicated in their announcement that existing users of Azure Trusted Signing would not be forcefully unenrolled. In other words, everyone who already has a certificate from Microsoft could just renew their certificates, and re-identify themselves after a year. Including me.
But there’s a catch. Each certificate includes a lot of personal information in them (such as your legal name, and street address). And Microsoft’s renewal process does not permit changing any of this data. Instead, when any of your personal information has changed, you essentially cannot renew your identity validation. Instead, you need to create an entirely new one, and — guess what — since I don’t live in North America, I was unable to do so.
Do you want to know what changed? I moved. Silly me! My address has changed, and as such, even though the button “Renew validation” was active for me, I couldn’t renew the existing validation. I needed a new validation, but new validations are only allowed for North American citizens. So no more identity validation for me.
This is what I mean with moving goalposts: I fulfilled all requirements for Microsoft, but Microsoft decided that this was no longer sufficient. Now I also had to live on another continent. This is a bit like how my Master thesis supervisor explained to me how the Taliban reigned in Afghanistan: Create new laws every day and move the goalposts constantly so that citizens are always busy understanding what’s currently legal and thus won’t protest.
The Zettlr project can be happy that we have some collaborators who do fulfill the new requirements of Microsoft, but I have seen some posts online that other projects aren’t as lucky. Those projects with no ability to use Microsoft’s own service now have the choice between a rock and a hard place: Either they let their own app “fall back” to a status in which their program is being treated as malware, even though it hasn’t been previously; or they bite the bullet and pay thousands of dollars in extortion for a company that is selling trust.
3. Certificate Providers See Selling Certificates as a Way to Turn a Profit
This is my third point of critique: Because Microsoft only controls the technical aspects of code signing certificates via its “Trusted Root Program,” companies are free to charge whatever they want for certificates. And since code signing is a very niche space, there are not many competitors. And this means that those few companies that do sell code signing certificates can essentially charge whatever they want for certificates.
Remember: While the server hardware required for certificates costs some money, and while getting your root certificates licensed by Microsoft is not cheap either, it does not justify the absurd prices they charge. And remember, these companies can issue as many code signing certificates as they want; certificates are not limited in supply. Apple charges $100 a year for the developer program. And this includes a ton of resources, early access to Beta releases, access to a code signing certificate and notarization servers (which is just another layer of security with Apple). So a code signing certificate that costs $100 is already much more expensive as it needs to be. More than a thousand dollars means that the markup these companies make is at least 100×.
However, we are talking about security here. We are not talking about a nice-to-have add-on for developers. We are talking about a critical security feature. And charging prescription-drug prices may feel very American, but it puts users at risk, and Microsoft should do more to prevent arbitrary prices from being charged by third-party companies.
Final Thoughts
How Microsoft treats code signing, it essentially says “Not my problem.” Thus, the company puts all users of its own operating system at risk. Because developers will not stop developing software. We enjoy what we do. So if we cannot fulfill your requirements, we are likely to recommend our users to disregard the security warning of Windows, and run unsigned code anyway. And by doing so, we train our users to disregard a warning that once could save their data. Or, we may stop providing software for Windows entirely. Especially smaller open source developers are not even considering providing Windows binaries anymore, because of all of these issues. And this will drive customers away from Windows. Because at a certain point, the lack of high-quality software for Windows will make more and more users consider alternatives.
What can explain this behavior by Microsoft? Actively endangering its own customer’s security? There are two possible explanations. The most obvious one is that Microsoft simply is not efficient; their internal processes are a mess, and the experience of anyone working with Windows and/or Microsoft is a testament to that.
But I believe that the reason Microsoft is so hostile to developers in particular is a different one. I believe – and this is my personal, subjective belief – that Microsoft does not want third-party developers. Interpreting the behavior of Microsoft in the past years, I think that they are en route to making Windows a business-only operating system. One that only runs on work computers, and is managed by company IT departments. Where the only software that runs is the one approved by either Microsoft or the company department. Everything else can be provided as web apps. And, since Microsoft has ported almost all of their software to web-apps, even most Microsoft products run on the web.
The only reason that Windows is still available for individual customers is because video games run predominantly on Windows, even though SteamOS closes the gap very fast. But outside of company uses, and the need to work with large Excel-spreadsheets, there is little to be gained by using Windows. Especially now that Linux is slowly starting to get more user-friendly.
Don’t get me wrong: As long as many users of Zettlr are on Windows, I will do everything in my power to ensure that Zettlr continues to run on Windows. But as soon as the amount of Windows users drops to a tiny fraction, I will become more picky. Not because I want to limit who can run Zettlr, but because Microsoft’s business practices are just a pain in the butt. Don’t worry, though: Currently, more than two thirds of Zettlr’s users are on Windows, so that day will not come anytime soon.