dotnet / sign

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

Click once manifest is not valid #629

Closed supervos closed 1 year ago

supervos commented 1 year ago

Describe the bug When installing a click-once application the issuer is shown as unknown. Verification of the manifest also shows that it does not have a valid signature.

Repro steps Executing the following script:

MSBuild.exe project.sln `
    -p:configuration=Release `
    -m -nr:false `
      -detailedSummary `
      -p:DeployOnBuild=true `
      -p:WebPublishMethod=FileSystem `
      -p:MapFileExtensions=true `
      -p:"PublishDir=$pwd/_build/output/" `
      -p:"InstallUrl=https://example.com/product/"

remove-item @("$pwd/_build/output.zip", "$pwd/_build/output.clickonce") -ErrorAction SilentlyContinue

compress-archive $pwd/_build/output/* -DestinationPath $pwd/_build/output.zip

rename-item  $pwd/_build/output.zip -NewName  $pwd/_build/output.clickonce

dotnet tool update --tool-path . sign --version 0.9.1-beta.23203.3

.\sign code azure-key-vault --verbosity trace -m 1 `
    $pwd/_build/output.clickonce `
    --publisher-name "publisher" `
    --description "product" `
    --description-url https://example.com/ `
    --azure-key-vault-tenant-id "$tenantId" `
    --azure-key-vault-client-id "$clientId" `
    --azure-key-vault-client-secret "$clientSecret" `
    --azure-key-vault-certificate "$certificateName" `
    --azure-key-vault-url "https://$vaultName.vault.azure.net/"

remove-item "$pwd/_build/output.zip" -ErrorAction SilentlyContinue
rename-item  $pwd/_build/output.clickonce -NewName  $pwd/_build/output.zip

remove-item $pwd/_build/artifact/ -Recurse
expand-archive $pwd/_build/output.zip -DestinationPath $pwd/_build/artifact/

mage.exe -ver $pwd/_build/artifact/project.application

mage.exe -ver "$pwd/_build/artifact/Application Files/*/project.exe.manifest"

Expected behavior Manifest has a valid signature.

Actual behavior

ASN1 bad tag value met.

Manifest does not have a valid signature.

Additional context

Runtime Environment: OS Name: Windows OS Version: 10.0.19045 OS Platform: Windows RID: win10-x64 Base Path: C:\Program Files\dotnet\sdk\7.0.203\

Host: Version: 7.0.5 Architecture: x64 Commit: 8042d61b17

.NET SDKs installed: 2.1.701 [C:\Program Files\dotnet\sdk] 2.1.818 [C:\Program Files\dotnet\sdk] 3.1.426 [C:\Program Files\dotnet\sdk] 5.0.103 [C:\Program Files\dotnet\sdk] 5.0.104 [C:\Program Files\dotnet\sdk] 5.0.203 [C:\Program Files\dotnet\sdk] 5.0.214 [C:\Program Files\dotnet\sdk] 5.0.303 [C:\Program Files\dotnet\sdk] 5.0.408 [C:\Program Files\dotnet\sdk] 6.0.202 [C:\Program Files\dotnet\sdk] 6.0.203 [C:\Program Files\dotnet\sdk] 6.0.311 [C:\Program Files\dotnet\sdk] 7.0.203 [C:\Program Files\dotnet\sdk]

.NET runtimes installed: Microsoft.AspNetCore.All 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.All 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.All 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 3.1.15 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 6.0.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 7.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.NETCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.1.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 7.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.WindowsDesktop.App 3.1.15 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 5.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 5.0.9 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.15 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.16 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 7.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found: arm64 [C:\Program Files\dotnet] registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\arm64\InstallLocation] x86 [C:\Program Files (x86)\dotnet] registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables: Not set

global.json file: Not found

Learn more: https://aka.ms/dotnet/info

Download .NET: https://aka.ms/dotnet/download

- Add any other context about the problem here.
Here is the verbose output that mentions that the manifest and application are signed

[...] info: Sign.Core.IMageCli[0] Running mage.exe with parameters: '-update "%tmp%\0yd3wdgk.vt4\Application Files\project_2_7_1_17385\project.exe.manifest" -a sha256RSA'. info: Sign.Core.IMageCli[0] mage.exe returned the output project.exe.manifest successfully updated

info: Sign.Core.ISignatureProvider[0] Signing succeeded. info: Sign.Core.IMageCli[0] Running mage.exe with parameters: '-update "%tmp%\0yd3wdgk.vt4\project.application" -a sha256RSA -appm "%tmp%\0yd3wdgk.vt4\Application Files\project_2_7_1_17385\project.manifest" -pub "publisher" -SupportURL https://example.com/'. info: Sign.Core.IMageCli[0] mage.exe returned the output project.application successfully updated

info: Sign.Core.ISignatureProvider[0] Signing succeeded.



This is tried with a self signed code certificate and an official purchased certificate from GlobalSign.

calling mage with a certificate on an usb token generates the expected behavior.
supervos commented 1 year ago

Issue found, it seems that there is an extra <Object><as:Timestamp>[...]</as:Timestamp></Object> in the Signature node, just below the KeyInfo.

This causes the validation to fail.

I don't know how to make this field optional or what the correct format of the timestamp should be.

dtivel commented 1 year ago

Thanks for the report, @supervos.

I don't see an extra <Object /> node; I see exactly 1, which is expected for a timestamp. If you see more than one, please share repro steps so I can see what you see.

The issue I see with your repro steps is that the value in the <Object /> node is not a valid Base64-encoded timestamp.

The default timestamping service is http://timestamp.acs.microsoft.com. If you use this default timestamping service, this issue reproes. If you use another timestamping service (e.g.: http://timestamp.digicert.com), this issue does not repro and the manifests will validate successfully using mage.exe -ver.

I haven't yet figured out why this problem reproes with http://timestamp.acs.microsoft.com, but for now using another trusted timestamping service should work around the issue.

CC @clairernovotny

dtivel commented 1 year ago

@supervos, I found 3 bugs here:

  1. https://github.com/dotnet/deployment-tools/issues/275
  2. https://github.com/dotnet/msbuild/issues/8755
  3. https://github.com/dotnet/sign/issues/630

If your publisher signing certificate has a signature algorithm other than RSA SHA-256, then you'll hit all 3 issues. You can work around the first 2 issues by using another timestamping service, like http://timestamp.digicert.com. Until the 3rd issue is fixed, your timestamps will still have a SHA-1 message imprint.

CC @clairernovotny

supervos commented 1 year ago

Hello @dtivel,

Thank you for your reply and investigation of this.

We never did a timestamp on the manifest, only on the excecutables, that's why I saw this node as 'extra' I have tried the signing with our normal timestamp service but that one only allows a single request (no multithreading) but the sign still uses multiple threads (even when setting -m 1).

I have created a fork where I have removed the timestamping of the manifest until this is fixed.

dtivel commented 1 year ago

Thanks for the thanks, @supervos.

The latest package version (0.9.1-beta.23274.1) on https://nuget.org has this fix, which enables Sign CLI to timestamp ClickOnce manifests with RFC 3161 timestamp, especially with the default timestamping service (http://timestamp.acs.microsoft.com).

There is an important caveat that comes with this updated version. https://github.com/dotnet/deployment-tools/issues/275 is still unresolved as I write this. Because that issue is the purview of another product/team, I don't have a timeline for a fix for it. That means that my fix will only work if you work around that issue by using a signing certificate with the sha256RSA signature algorithm -OR- by using a different, more lenient timestamping service.

I have tried the signing with our normal timestamp service but that one only allows a single request (no multithreading) but the sign still uses multiple threads (even when setting -m 1).

If you have a repro, can you please open a new issue so I can investigate?

Otherwise, I'll close this issue since the latest version of Sign CLI supports RFC 3161 timestamping and the other issues are tracked in other repositories. Known issues for Sign CLI 0.9.1 are tracked here.