sigstore / fulcio

Sigstore OIDC PKI
Apache License 2.0
650 stars 138 forks source link

Documentation on signing Windows and MacOS apps #250

Closed maltfield closed 1 month ago

maltfield commented 2 years ago

After reading your README.md, the elephant missing is: how do I actually sign my releases using a fulcio-issued code signing certificate for Windows and MacOS?

Context: I maintain an open-source project. I sign my releases with PGP and provide documentation to my users on how they can cryptographically verify the authenticity of my releases using gpg. However, despite this, my Windows and MacOS users get annyoing alerts about "untrusted software".

Because I'm an Open Source project without a budget, I'm not about to go pay $100/year for a code signing certificate to be used in the Microsoft ecosystem or an additional $200/year for another certificate for Apple.

So when I saw that sigstore provides temprory-issued code signing certificates like Let's Encrypt does for websites, I was stoked that I may be able to smooth-out this annoyance for my users. But I couldn't find a guide on how to do this.

Please document:

  1. How to sign a given .exe using a fulcio-issued code signing certificate for Microsoft OSes
  2. How to sign a given .dmg using a fulcio-issued code signing certificate for Apple OSes
bobcallaway commented 2 years ago

There's nothing conceptually preventing the use of sigstore services for the Windows or MacOS ecosystems, but since the sigstore public Fulcio instance isn't in the trust stores of either operating system by default, you would still have the same UX of having to click through a warning.

We could document the current path but I think most users would be left with the same frustration you described. Solving this for Windows and MacOS is definitely on our radar but we have a bit of a :chicken: / :egg: problem :/

maltfield commented 2 years ago

So if fulcio is the "Let's Encrypt for code signing" then this begs the question:

Question: How did Let's Encrypt get into the trusted root store? Answer: Let's Encrypt's CA was cross-signed by Identrust on October 19, 2015.

So then the questions that follow are:

  1. How do we get a list of all the CAs in the trust stores for Microsoft and Apple Operating Systems?
  2. Which of the above CAs are friendly with Open Source?

And also:

  1. Who do we know at Microsoft and Apple that can help make this a reality?
jcotton42 commented 2 years ago

Just my own two cents, but I think documenting this would have a positive effect on adoption. Right now you're not going to have the attention of any Windows or macOS devs because they won't even be able to figure out how to sign their own apps, even if it's just for the purposes of playing around. But if you do document it you might garner some interest, which may reach the ears of Apple and Microsoft.

Foxboron commented 2 years ago

For Microsoft there are a few options since Microsoft Authenticode is effectively used for codesigning under Secure Boot. I have written a lot of code for this in Go so writing a utility to get valid signing for EFI executables was fairly trivial:

https://github.com/Foxboron/authenticode-fulcio

But I'm not sure how this would fare on an real Windows binaries. Hooking it up certificate generation from fulcio and handing the certificate to something like https://github.com/rhboot/pesign or https://github.com/mtrojnar/osslsigncode should also be fairly easy to write examples for.

What is the codesigning utility for macOS?

Foxboron commented 2 years ago

I tried to sign a PE file with my tooling + a few others to see if I could get something valid. But it seems like there is something missing in the certificate chain as none of the tools are capable of creating a valid signature. There is also an issue where the binary would only have a valid signature for 20 minutes so I'm not super sure about the practical use-case yet.

Need to try read a bit more up on Microsoft Authenticode and figure out what is missing.

jcotton42 commented 2 years ago

Any update on this? Free signing for Windows and macOS apps would be pretty great.

haydentherapper commented 2 years ago

There are no current plans to include the Fulcio root in the macOS or Windows trust stores. The way that Sigstore manages and updates its roots of trust through TheUpdateFramework is incompatible with the OSs' trust store requirements.

As for the short expiration, Authenticode supports including a signed timestamp. Sigstore is working on spinning up a timestamping authority (TSA), though you could also request a signed timestamp from a TSA like Digicert's. For any TSA where its root is not trusted by the OS, you will run into the same warnings.

re: https://github.com/sigstore/fulcio/issues/250#issuecomment-1019297096, there may be some X.509 extension or additional value that needs to be set in a Windows code signing certificate. We have a specification for issued certificates in our docs.

Happy to include documentation in this repo if someone wants to explore how to use Fulcio to sign Windows or macOS apps.

Adrianotiger commented 2 years ago

I really hope, Microsoft can find a solution for this... image

Maybe integrating Fulcio for open source projects.

9072997 commented 1 year ago

Just a note here, but Smart Screen (which IMHO is the main reason to sign code on Windows) treats OV and EV certificates differently. EV certificates are trusted by default (assuming the CA is trusted) while OV certificates just allow you to pool the reputation of all the executables they have signed. Here are some examples:

If you are forced to use OV certificates (for example because EV code signing certificates are not available to individuals) there are 2 tricks to minimizing warnings:

I say all this to say: 10-minute OV certificates are not useful with respect to Smart Screen. I would love it if we could convince Microsoft that a subject rather than a certificate should build reputation, but I imagine you would need some serious pull with Microsoft to make that happen.

equeim commented 1 year ago

Another reason for code signing is that it is needed for "modern" Windows 10/11 applications. Modern Windows 10/11 apps are required to be either:

  1. Published in Microsoft Store (in which case they are automatically signed my Microsoft's certificate)
  2. Packaged using MSIX format and signed with expensive certificate that you bought from CA that Microsoft trusts. If you don't do that then it won't be just a warning that you can click through, Windows will outright refuse to install your app.

Why would you want it besides migrating away from ancient MSI/exe installers? It provides better integration with OS because it now has an actual concept of "application" instead of a bunch of random values in registry, it provides easier ways to do basic tasks such as registering file type associations, and more importantly: some new Windows APIs simply won't work if your app is not an "application" in Windows 10 terms.

However, because for such apps code signing is now enforced by OS, many people are unable (including myself) or unwilling to package their apps in a modern way. Having open source and free tool for code signing will go a long way to help this. I hope Microsoft realises it too at some point.

sealsrock12 commented 1 year ago

@9072997 the other main reason is to have the UAC prompt be from a "verified publisher," and not be an intimidating yellow

Dunkhan commented 1 year ago

Why would you want it besides migrating away from ancient MSI/exe installers? It provides better integration with OS because it now has an actual concept of "application" instead of a bunch of random values in registry, it provides easier ways to do basic tasks such as registering file type associations, and more importantly: some new Windows APIs simply won't work if your app is not an "application" in Windows 10 terms.

MISX is a complete dumpster fire. I tried it in a production environment last year and I can link you the litany of bugs that microsoft refuses to fix or in some cases even acknowledge. Bugs with multi-page lists of loyal windows developers panicking that they are going to get fired for failing to be able to deploy a working application to their customers. In the end I had to write a lot of custom code to work around janky implementation mistakes in the MSIX and Windows application installer libraries.

Given that, and the comments on this issue, I feel like the best way forward is for everyone to start telling users 'we don't support windows anymore, there is a version you can install but you will have to jump through some hoops to get it working. Report your problems to windows or switch OS.'

Their market share is dropping and linux is getting easier to switch to. Let's put the ball back in their court.

DRSchlaubi commented 1 year ago

Just dropping support for Windows completely sounds like a terrible idea, sure the market share might be dropping, but it's still the most popular OS by a long shot.

Also, the signing situation on Windows just got worse. You used to be able to sign your apps with an OV signing certificate, which was available for "just" 100$, However, those prices just tripled, because now you have to store the private keys on FIPS compliant hardware. Having a way out for open source projects is more important than ever, however Microsoft, as usual, just pretends we don't exist

gbakeman commented 1 year ago

I've been following this issue for some time, in the hopes that free or low-cost code signing may soon become available for Windows distributions. After re-reading the topic, can anyone help me understand why the following two workarounds aren't tenable?

  1. Fulcio is cross signed like Let's Encrypt
  2. Ask the user to manually install the Fulcio CA into their cert store
DRSchlaubi commented 1 year ago

I've been following this issue for some time, in the hopes that free or low-cost code signing may soon become available for Windows distributions. After re-reading the topic, can anyone help me understand why the following two workarounds aren't tenable?

  1. Fulcio is cross signed like Let's Encrypt
  2. Ask the user to manually install the Fulcio CA into their cert store

Probably as was stated here https://github.com/sigstore/fulcio/issues/250#issuecomment-1208166997 the certificates don't comply with trust requirements, as Authenticode trusted certificates also certify the legal identity of the signer, so if a CA cross-signed fulcio they would probably get untrusted

as for why users not being able to install the certificate idk

andrewleech commented 1 year ago

2. Ask the user to manually install the Fulcio CA into their cert store

In my opionion that basically defeats the purpose; you can already ask users to install any self-signed cert/ca and then install your app signed with it. Indeed, tools like Zadig self-sign the automatically generated drivers it creates, installs the cert and then installs the driver all in one "admin approved" operation.

Someone security conscious would certainly prefer to install a CA like Fulcio rather than any "random developer" CA, however in reality most users are not that security literate.

gbakeman commented 1 year ago

If not by being accepted into the root stores or even cross-signed, then I have to wonder if convincing users to install the master/root CA may be the only option. It would require an education campaign, maybe explain how security requires establishing trust and how Fulcio works in that regard. But if we want to break into what feels like a proprietary walled garden and start building a network of trust in the FOSS world, I think it's going to take some convincing of the masses.

haydentherapper commented 1 year ago

Adding onto https://github.com/sigstore/fulcio/issues/250#issuecomment-1676421642, the requirements for inclusion into a trust root are not feasible for an open source project. For example, Microsoft's requirements include a yearly audit, which would be prohibitively costly.

As for "Ask the user to manually install the Fulcio CA into their cert store", there are no technical blockers for users who choose to include the Fulcio root in their trust store. As I noted in https://github.com/sigstore/fulcio/issues/250#issuecomment-1208166997, Sigstore distributes its roots of trust using TheUpdateFramework. Users would have to monitor Sigstore's TUF repository to keep up to date with the latest roots. This isn't a great UX.

Also note that a key part of Sigstore's threat model includes transparency for signing events. Artifact inclusion into a transparency log is checked by Sigstore clients, but would not be checked by the operating system.

If someone would like to author documentation for using Sigstore with Windows/macOS, or create a daemon that loads Fulcio's root from TUF into the OS trust root, I'd be happy to review.

JoanCharmant commented 1 year ago

I am also looking into this as an individual developer of open source Windows applications. The current state of affairs doesn't make financial sense for small/individual projects.

How about a solution like the following:

Trust model:

Anyone seeing a problem in this approach? I have no experience with Mac so I don't know if the same model could be used.

ChristianGalla commented 1 year ago

I am not sure if using a $300/year certificate of one vendor for such a use case is against their contracts, so this should be checked first. Maybe it is also possible to contact such a vendor or Microsoft and create a special contract for this organization.

Uploading files to a central organization has some drawbacks. Maybe this can be reduced by only uploading file hashes?

Pros of using hashes:

Drawbacks of using hashes:

Also, there should be some validation of the developer and transparency of what has been signed. Therefore, I suggest the following:

  1. At least one way of validation of the developer. I suggest something automated like the Let's Encrypt way, for example "this file has been signed for the owner of the domain example.org as of YYYY-MM-DD".
  2. A public list that includes all signed hashes, the developer, and the sign date. The file name is not needed.
  3. This list should also include, and mark withdrawn hash certificates, for example if one hash was for malicious software or a developer has been hacked.
quyse commented 1 year ago

@JoanCharmant Well this organization has to assume the responsibility for the signed binaries. If the org will be working only with a small closed circle of vetted developers, I guess it may work, but it does not change the big picture, and a bunch of developers can just as well start a company together for that purpose today (or some sort of non-profit or unofficial partnership).

However if this organization will actually try to be open and allow anyone to sign their binaries, some malware will inevitably slip through, and the cert will be revoked by the parent CA. Even if the org tries to do thorough identity verification of developers similarly to what existing CAs do, since it is not officially a CA it is not as "protected" from actions of its users as regular CAs, and legally signs binaries on its own behalf. I would expect the cert of the org to be revoked very quickly.

maltfield commented 1 year ago

@ChristianGalla file hashes do not provide cryptographic authenticity. They provide integrity.

To securely transfer the authenticity of a set of files, you'd need signatures -- not hashes (or a manifest file with hashes that itself is signed).

ChristianGalla commented 1 year ago

@maltfield of course I mean normal digital signatures using hashing (HMAC).

Usually, a digital signature / certificate is computed and used the following way:

  1. Calculate the hash of the data to sign. This hash is easy to calculate but hard to reverse. Also, the hash has a fixed length, so is usually much shorter than the data. Additionally, even if only a small part of the data is changed, another hash would be computed.
  2. The hash is encrypted using a private key of an asymmetric encryption.
  3. Attaching of the signature to the data.
  4. When validating the signature, the corresponding public key is used to decrypt the signature. If the decrypted hash is the same as a new one calculated from the data, the data has not been changed and only the owner of the private key was able to create the signature.

This way, a digital signature guarantees authenticity and integrity, because both are needed.

In my proposal, step 1 could be computed on the local computer of the developer and only step 2 in the environment of the organization.

J5lx commented 1 year ago

@JoanCharmant I think you’re looking for the SignPath Foundation. They sign Windows binaries for projects like Mumble or Vim. See also here.

teras commented 1 year ago

@JoanCharmant I think you’re looking for the SignPath Foundation. They sign Windows binaries for projects like Mumble or Vim. See also here.

I think the price of 500$ defies the reason to use it in the first place. The main idea, the way I see it, is how an open source developer with limited resources to be able to sign for windows applications, given that himself is giving not only thr app, but also the code for free.

paulsavoie commented 1 year ago

I think the price of 500$ defies the reason to use it in the first place.

Disclaimer: I work for SignPath Just wanted to clarify that for approved OSS projects, the SignPath Foundation provides free code signing certificates and of course the usage of our services are also free.

agarny commented 1 year ago

I think the price of 500$ defies the reason to use it in the first place.

Disclaimer: I work for SignPath Just wanted to clarify that for approved OSS projects, the SignPath Foundation provides free code signing certificates and of course the usage of our services are also free.

From what I can tell (https://about.signpath.io/product/editions), it's a standard (OV) certificate, not EV certificate. So, people would still get warnings (as per https://github.com/sigstore/fulcio/issues/250#issuecomment-1289258324).

paulsavoie commented 11 months ago

From what I can tell (https://about.signpath.io/product/editions), it's a standard (OV) certificate, not EV certificate. So, people would still get warnings (as per #250 (comment)).

Hi @agarny, that's correct, there are warnings until Microsoft SmartScreen has seen the software often enough in the wild and decides that it can omit the warnings, then they go away. We are considering providing EV certificate for OSS projects at SignPath also, but are not quite there yet.

teras commented 11 months ago

Hi @agarny, that's correct, there are warnings until Microsoft SmartScreen has seen the software often enough in the wild and decides that it can omit the warnings, then they go away. We are considering providing EV certificate for OSS projects at SignPath also, but are not quite there yet.

We are looking forward to it :)

Since usually open source projects it's common to have bursts of releases, and "desert" time periods with no releases at all, instead of having timely releases, waiting for SmartScreen to decide when an application is "safe", is not a viable solution.

arianvp commented 1 month ago

It seems GitHub now has its own Root CA that supports Fulcio:

https://github.blog/news-insights/product-news/introducing-artifact-attestations-now-in-public-beta/#github-is-now-a-root-certificate-authority

Idk if that means if the Root CA is actually trusted by Microsoft. But given it's a Microsoft product I would hope that it is?

pl4nty commented 1 month ago

@arianvp that GitHub root CA isn't in the Windows trust store: https://learn.microsoft.com/en-us/security/trusted-root/participants-list

I'd be surprised if there were any plans to trust the CA, because GitHub are using TUF (like Fulcio) which doesn't meet Microsoft's requirements: https://github.com/sigstore/fulcio/issues/250#issuecomment-1208166997

For Windows codesigning, it's worth considering Azure Trusted Signing: https://azure.microsoft.com/en-us/products/trusted-signing It's only for businesses at the moment, but they're working on support for individual developers

haydentherapper commented 1 month ago

Closing this issue as there are no other topics for discussion.

paulsavoie commented 1 month ago

Just wanted to follow up on @pl4nty's comment: Whiel Azure Trusted Signing is just for businesses, we provide free code signing for OSS projects at SignPath.org. (Disclaimer: I work at SignPath)

mlocati commented 2 weeks ago

we provide free code signing for OSS projects at SignPath.org

Thanks for the tip, @paulsavoie! I managed to use SignPath to easily sign my Windows exe and dll files with just a couple of GitHub Action steps!! ❤️

p0358 commented 3 days ago

@paulsavoie Question about the SignPath policy: it states that third-party libraries should be signed by upstream, but that only makes sense for dynamic libraries (.DLLs), statically compiled ones cannot be signed for obvious reasons. The policy also mentions that unsigned binaries of other projects can be included in signed packages such as installers.

But what about statically compiled libraries? It doesn't seem to straight up say anything about it. It's kinda hard to build any executable without linking anything to it most of the time. Even something like Microsoft's CRT I'm not sure if it qualifies as a system library technically if it's not included with the OS and is meant to be shipped as vcredist.exe with the app (or just statically linked, which is sometimes beneficial to do for some technical reasons).

Would static libraries be fine if they're relatively small and the entire/part of the code was adopted directly into the repo? Would they be fine if they're attached as a git submodule to the repo? (thus linking main repo's commit SHA with particular submodule repo SHA, also guaranteeing the source code that the main SHA corresponds to) This would be assuming that all the code was read and reviewed by maintainers before being used.

Currently it feels like the sentiment is somewhere "in between", but it'd be nice if there were some clarifications that'd give project owners some official flexibility in this regard, but in a way that wouldn't compromise security (for example submodules compiled by CI are fine, but some package systems where a version number can be replaced with a different hash if it's not pinned by hash - not necessarily; perhaps adding the clause that code should be reviewed on inclusion and updates or something? and perhaps with exception of bigger libraries that are already being signed in some form, which'd be a similar thing to current policy of signing forks).

My motivation for asking is that splitting code into 20 DLLs of some tiny parts would be kinda infeasible if no linking at all was allowed, both from portability standpoint (can't download one dll for a hypothetical plugin program for example, have to download and unpack a zip, whose deps might conflict with other plugins then, there's a few more examples like that I can think of), and performance (external symbols means LTCG can't perform any optimizations/inlines of frequently used function, no removal of dead (unused) code could also occur).

fire commented 3 days ago

https://docs.velopack.io/packaging/signing describes another way to code sign that isn't exceedingly expensive.

Azure Trusted Signing (ATS).

Costs USD$10/mo (or USD$120/yr) which is on-par or cheaper than code signing certificates from other issuers. Full cloud solution / Does not require any physical hardware (HSM) shipped to you. Signing can be automated (eg. in your CI pipeline) ATS certificates get built-in instant reputation for smart-screen and defender.

The physical hardware module requirement is a difficult barrier.

p0358 commented 3 days ago

Azure Trusted Signing

You’ll need a biz with 3 years of history to use Trusted Signing! Microsoft says “Trusted Signing at this time can only onboard Legal Business Entities that have verifiable tax history of three or more years.” If you don’t have a registered business with paperwork, or if it’s younger than 3 years, you will have to wait until they launch “personal” validation. As of August 2024 Microsoft is actively working on it. I have also heard reports of businesses younger than 3 years passing identity validation. https://melatonin.dev/blog/code-signing-on-windows-with-azure-trusted-signing/

https://github.com/Azure/trusted-signing-action/issues/42