sign icon indicating copy to clipboard operation
sign copied to clipboard

Azure Trusted Signing fails when using Public Trust test certificates

Open kauppine opened this issue 5 months ago • 5 comments

Describe the bug When using Azure Trusted Signing with a Public Trust test certificate, the signing fails. Using a non-testing certificate from the same Trusted Signing Account works as intended. Based on my own testing this has worked at least ~6 months ago. I tested older versions of dotnet sign and it does not work with those either.

What I haven't done is testing with .NET 8.

Repro steps I created a simple console app and tried to sign the exe with the following command: sign code trusted-signing -tse https://weu.codesigning.azure.net/ -tsa trusted-signing-account -tscp signing-profile-test .\*.exe -v trace

Expected behavior The files should be signed successfully.

Actual behavior Dotnet sign fails with error Failed to build chain for certificate.

Additional context

  • Include the output of sign --version.
  • Include the output of dotnet --info.
  • Add any other context about the problem here.
 PS C:\Users\user\sources\ConsoleApp1\bin\Debug> sign code trusted-signing -tse https://weu.codesigning.azure.net/ -tsa trusted-signing-account  -tscp signing-profile-test .\*.exe -v trace
trce: Sign.SignatureProviders.TrustedSigning.TrustedSigningService[0]
      Fetching certificate from Trusted Signing certificate profile.
trce: Sign.SignatureProviders.TrustedSigning.TrustedSigningService[0]
      Fetched certificate. [2368.8501 ms]
trce: Sign.SignatureProviders.TrustedSigning.TrustedSigningService[0]
      Certificate details:
      [Version]
        V3

      [Subject]
        CN=Organization name(TEST ONLY), O=Organization name, L=Country, S=Region, C=C
        Simple Name: Organization name(TEST ONLY)
        DNS Name: Organization name(TEST ONLY)

      [Issuer]
        CN=Microsoft Developer ID Test CS AOC CA 02, O=Microsoft Corporation, C=US
        Simple Name: Microsoft Developer ID Test CS AOC CA 02
        DNS Name: Microsoft Developer ID Test CS AOC CA 02

      [Serial Number]
        330024D2252D0A7B1DB4C7150200010024D225

      [Not Before]
        21/07/2025 4.56.37

      [Not After]
        24/07/2025 4.56.37

      [Thumbprint]
        8E7B8068F369046F8572C63B27D02CB31971FC71

      [Signature Algorithm]
        sha384RSA(1.2.840.113549.1.1.12)

      [Public Key]
        Algorithm: RSA
        Length: 3072
        Key Blob: 30 82 01 8a 02 82 01 81 00 9a c2 28 2a bc 4a 32 d3 0c 3b e1 7e cf 93 11 73 70 11 a2 2b a8 35 81 03 64 55 70 99 2f 9b 0d 8e 77 c5 1e 52 51 13 55 09 0c f5 f4 bf 8a 53 b1 e2 26 cb 8d bb b2 15 ad a8 40 da 5e a6 bc d2 e9 ab 22 4e 1e 78 14 1b c7 3a ca 38 74 a7 5b f6 6f 7b 4f ad 99 cc 7c f9 56 79 da 38 f2 b0 65 3d 0a 8a b8 cc 37 09 03 7e 94 1c 4c 21 c4 7f 7e 0b 0e cf 2d 48 4e a7 42 fd fc 5b 40 66 2d 90 23 05 04 20 6f 0a 38 a1 ba d1 13 c8 11 54 07 b9 96 e8 34 2a 77 e9 02 e5 ce 98 22 97 f4 26 17 cf 23 75 f0 49 bb d9 10 ac b5 15 e6 80 50 b1 1e 97 e9 aa 20 2f cc 7a f2 53 a0 12 f3 a5 c9 b0 66 93 1c ff c6 6d 11 d6 0c ab 3a 01 a4 c5 8e b9 a8 69 0f 02 36 74 67 90 c0 ac 41 20 10 8e 72 43 73 0c 84 02 84 ac a0 2d e2 0f c0 ac 44 eb d9 ae 7b e6 59 6d 57 80 bd e1 d1 84 2b a9 3d 7a cd 46 d0 79 e5 85 88 e0 fb aa 43 c7 fe c8 10 85 29 77 ef 84 42 6f ec 9f 5d 1c ef 97 2e 5e 6a 56 8b f0 73 5e f5 83 96 87 75 93 fa ae 1b 1d 75 1c 60 89 9c fd cd 0e a3 d2 ff b0 ee dd 86 1c 4d 83 6c 44 3e 62 59 b3 2c 60 93 4d 5c 9a c8 65 ed ec 7a 90 12 de 55 4b fa 8c 81 aa ec 31 65 74 1c c1 4a 13 2f 18 a6 09 35 cb 76 7e 71 df 9d 7e f2 a7 7b 94 5a 58 5b 01 c4 8f c9 f6 37 91 49 e6 b1 99 af 50 17 fc 1e 13 c5 cd 02 03 01 00 01
        Parameters: 05 00

      [Extensions]
      * Basic Constraints(2.5.29.19):
        Subject Type=End Entity
      Path Length Constraint=None

      * Key Usage(2.5.29.15):
        Digital Signature (80)

      * Enhanced Key Usage(2.5.29.37):
        Code Signing (1.3.6.1.5.5.7.3.3)
      Lifetime Signing (1.3.6.1.4.1.311.10.3.13)
      Unknown Key Usage (1.3.6.1.4.1.311.97.1.2.740251510.862486973.67201376.284453507)

      * Subject Key Identifier(2.5.29.14):
        9651bcda79bbe09dc0e160804855529f2159bef0

      * Authority Key Identifier(2.5.29.35):
        KeyID=cf9019e7d9132a69bd980868f94c7802cff96f48

      * CRL Distribution Points(2.5.29.31):
        [1]CRL Distribution Point
           Distribution Point Name:
                Full Name:
                     URL=http://www.microsoft.com/pkiops/crl/Microsoft Developer ID Test CS AOC CA 02.crl (http://www.microsoft.com/pkiops/crl/Microsoft%20Developer%20ID%20Test%20CS%20AOC%20CA%2002.crl)

      * Authority Information Access(1.3.6.1.5.5.7.1.1):
        [1]Authority Info Access
           Access Method=Certification Authority Issuer (1.3.6.1.5.5.7.48.2)
           Alternative Name:
                URL=http://www.microsoft.com/pkiops/certs/Microsoft Developer ID Test CS AOC CA 02(1).crt (http://www.microsoft.com/pkiops/certs/Microsoft%20Developer%20ID%20Test%20CS%20AOC%20CA%2002(1).crt)


info: Sign.Core.ISigner[0]
      Submitting C:\Users\user\sources\ConsoleApp1\bin\Debug\ConsoleApp1.exe for signing.
trce: Sign.Core.IDirectoryService[0]
      Creating directory C:\Users\user\AppData\Local\Temp\vvrcejya.m4p.
info: Sign.Core.ISigner[0]
      SignAsync called for C:\Users\user\sources\ConsoleApp1\bin\Debug\ConsoleApp1.exe. Using C:\Users\user\AppData\Local\Temp\vvrcejya.m4p\mxng0pkc.exe locally.
info: Sign.Core.IDataFormatSigner[0]
      Signing SignTool job with 1 files.
trce: Sign.Core.IDirectoryService[0]
      Deleting directory C:\Users\user\AppData\Local\Temp\vvrcejya.m4p.
trce: Sign.Core.IDirectoryService[0]
      Directory C:\Users\user\AppData\Local\Temp\vvrcejya.m4p deleted.
fail: Sign.Core.ISigner[0]
      Failed to build chain for certificate.
      System.InvalidOperationException: Failed to build chain for certificate.
         at AzureSign.Core.AuthenticodeKeyVaultSigner..ctor(AsymmetricAlgorithm signingAlgorithm, X509Certificate2 signingCertificate, HashAlgorithmName fileDigestAlgorithm, TimeStampConfiguration timeStampConfiguration, X509Certificate2Collection additionalCertificates)
         at Sign.Core.AzureSignToolSigner.SignAsync(IEnumerable`1 files, SignOptions options) in /_/src/Sign.Core/DataFormatSigners/AzureSignToolSigner.cs:line 110
         at Sign.Core.AggregatingSigner.SignAsync(IEnumerable`1 files, SignOptions options) in /_/src/Sign.Core/DataFormatSigners/AggregatingSigner.cs:line 92
         at Sign.Core.Signer.<>c__DisplayClass3_0.<<SignAsync>b__0>d.MoveNext() in /_/src/Sign.Core/Signer.cs:line 157
      --- End of stack trace from previous location ---
         at System.Threading.Tasks.Parallel.<>c__53`1.<<ForEachAsync>b__53_0>d.MoveNext()
      --- End of stack trace from previous location ---
         at Sign.Core.Signer.SignAsync(IReadOnlyList`1 inputFiles, String outputFile, FileInfo fileList, Boolean recurseContainers, DirectoryInfo baseDirectory, String applicationName, String publisherName, String description, Uri descriptionUrl, Uri timestampUrl, Int32 maxConcurrency, HashAlgorithmName fileHashAlgorithm, HashAlgorithmName timestampHashAlgorithm) in /_/src/Sign.Core/Signer.cs:line 86

Sign version and dotnet info:

PS C:\Users\user\sources\ConsoleApp1\bin\Debug> sign --version
0.9.1-beta.25330.2+dc01dca32471b368ad640358778e172d1bd249f9
PS C:\Users\user\sources\ConsoleApp1\bin\Debug> dotnet --info
.NET SDK:
 Version:           9.0.103
 Commit:            96da45d427
 Workload version:  9.0.100-manifests.ea610b94
 MSBuild version:   17.12.24+90b52dda6

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.22631
 OS Platform: Windows
 RID:         win-x64
 Base Path:   C:\Program Files\dotnet\sdk\9.0.103\

.NET workloads installed:
There are no installed workloads to display.
Configured to use loose manifests when installing new manifests.

Host:
  Version:      9.0.2
  Architecture: x64
  Commit:       80aa709f5d

.NET SDKs installed:
  9.0.103 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  [Microsoft.AspNetCore.App](http://microsoft.aspnetcore.app/) 6.0.36 [C:\Program Files\dotnet\shared\[Microsoft.AspNetCore.App](http://microsoft.aspnetcore.app/)]
  [Microsoft.AspNetCore.App](http://microsoft.aspnetcore.app/) 8.0.13 [C:\Program Files\dotnet\shared\[Microsoft.AspNetCore.App](http://microsoft.aspnetcore.app/)]
  [Microsoft.AspNetCore.App](http://microsoft.aspnetcore.app/) 9.0.2 [C:\Program Files\dotnet\shared\[Microsoft.AspNetCore.App](http://microsoft.aspnetcore.app/)]
  [Microsoft.NETCore.App](http://microsoft.netcore.app/) 6.0.36 [C:\Program Files\dotnet\shared\[Microsoft.NETCore.App](http://microsoft.netcore.app/)]
  [Microsoft.NETCore.App](http://microsoft.netcore.app/) 8.0.13 [C:\Program Files\dotnet\shared\[Microsoft.NETCore.App](http://microsoft.netcore.app/)]
  [Microsoft.NETCore.App](http://microsoft.netcore.app/) 9.0.2 [C:\Program Files\dotnet\shared\[Microsoft.NETCore.App](http://microsoft.netcore.app/)]
  [Microsoft.WindowsDesktop.App](http://microsoft.windowsdesktop.app/) 6.0.36 [C:\Program Files\dotnet\shared\[Microsoft.WindowsDesktop.App](http://microsoft.windowsdesktop.app/)]
  [Microsoft.WindowsDesktop.App](http://microsoft.windowsdesktop.app/) 8.0.13 [C:\Program Files\dotnet\shared\[Microsoft.WindowsDesktop.App](http://microsoft.windowsdesktop.app/)]
  [Microsoft.WindowsDesktop.App](http://microsoft.windowsdesktop.app/) 9.0.2 [C:\Program Files\dotnet\shared\[Microsoft.WindowsDesktop.App](http://microsoft.windowsdesktop.app/)]

Other architectures found:
  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

kauppine avatar Jul 21 '25 09:07 kauppine

Thx for reporting this, I would believe this is not particularly related to sign cli, I'll take a look from the trusted signing's end.

Jaxelr avatar Aug 04 '25 19:08 Jaxelr

Looks like if we sign some bits, the root certificate is not being publicly trusted:

Image

But this shouldn't be the issue, since private trust is also not publicly trusted, and it is working.

I think the key is that the chain of public trust test is different than the rest of the profile types. I'm still investigating.

Jaxelr avatar Aug 04 '25 22:08 Jaxelr

Managed to check drilled down into the specific details of the chain build up failure, and it looks like were getting the following validation errors when building the chain:

  • System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.NotSignatureValid
  • System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.OfflineRevocation
  • System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.RevocationStatusUnknown

I'm going to track down internally our PKI team to discuss this issue with them.

Jaxelr avatar Aug 07 '25 21:08 Jaxelr

Looks like the Certificate Profile is the Test and not Public Trust profile. The certificate chain and root for Test is not publicly trusted. That profile type is only for private test signing and any trust would have to be opt-in. Additionally, the end-entity signing certs are Lifetime EKU bound, so even if you are opt-ing in trust and properly timestamping, the signature will only be valid for the life of the end-entity signing certificate to ensure they are only being used for test.

ianjmcm avatar Aug 07 '25 21:08 ianjmcm

What I find particularly interesting is that private trust (for example, since its not trusted by default) does work on this chain.build, because the root of Public Trust and Private Trust is coming still from Microsoft Enterprise Identity Verification Root Certificate Authority 2020 while Public Trust Test is coming from a completely different root Microsoft Identity Verification TEST ONLY Root Certificate Authority 2020. Hence this causes the experience of failing to sign when it verifies just for public trust test, out of the box.

edit: typos

Jaxelr avatar Aug 07 '25 22:08 Jaxelr