dotnet / sign

Code Signing CLI tool supporting Authenticode, NuGet, VSIX, and ClickOnce
MIT License
447 stars 84 forks source link

Unable to skip already signed files (for instance for publishing a website zip) #647

Open CZEMacLeod opened 8 months ago

CZEMacLeod commented 8 months ago

It would be useful when signing e.g. a zip file created by publishing a website, to only sign unsigned files. This way existing signatures on DLLs such as those distributed by Microsoft don't get overwritten, and there would be less overhead when using KeyVault HSM.

This might be indirectly related to #547 where the default action was changed to overwrite, and the fact that the documented force flag doesn't seem to exist. The options to skip, overwrite, or append a signature would seem to be appropriate instead of force.

If you select to skip existing signatures, it should (optionally?) check the existing signature is valid, then skip the file if it is. If it is not, then it should 'fall through' to overwrite. In the case where append is used, it should also check the existing signature.

At the moment, the only way of implementing this that I can see, is to pre-scan the files and generate a filelist, although it is not entirely clear how this would work with files inside nuget or zip files as the documentation around the --file-list command is a little unclear.

Version: 0.9.1-beta.23530.1+f4efed9e8fb3296f29497b90feb6548e506f2078

dtivel commented 7 months ago

CC @clairernovotny

Authenticode supports multiple signatures. It was planned that Sign CLI's default behavior was to append new signatures. However, last we checked a Windows API we use (SignerSignEx3(...)) did not support appending; instead, it overwrote an existing signature. The --force option in the draft specification is in a limbo state because we haven't a good solution yet.

That said, there is a way to skip already signed files using file lists. You would use a file list to exclude already signed files in a separate invocation of Sign CLI. File lists have one file pattern per line. Each pattern can be a glob pattern.

CZEMacLeod commented 7 months ago

@dtivel Yes - I had worked out that the filelist might be a way of doing it, however, I run the command on a directory with multiple .nuget files (sometimes up to 100), and to work out the list would have to open and scan each file in the archive to check if it is already signed and add the ones that aren't to the list. I'm not even sure how it would work with the multiple nuget files. Would I need to include a pattern to sign the nuget package itself too? If this is the only available mechanism, then perhaps a good example of how to do this would be an idea?

As the command is already opening and unzipping the files to sign them, it would be nice to be able to test the files to check if they already have a valid signature, and only sign those without the signature. I appreciate that append and/or overwrite were the original intention - however, adding the third option to skip would be useful.

I appreciate this would be an extra step in the logic, and might slow it down somewhat. However, it would be much easier than basically doing the same work twice.

You mention using SignerSignEx3 - is this used in the azure key vault code? I assumed the signing was actually done in the cloud in this case, as the key cannot be exported?

bradwilson commented 5 months ago

Does the file list skip specification include the ability to exclude files that are inside a NuGet package? Is the list in that case a relative path to the file inside the NuGet package?

ViktorHofer commented 5 months ago

Looking at the code, an exclude starts with a !. So maybe !xunit.abstractions.dll or !build\*\xunit.abstractions.dll would work for you? This feature definitely needs some documentation.

bradwilson commented 5 months ago

It's easier to just list the two files I want signed rather than the 6 I don't. 😂