How to sign binaries during publishing a single file dotnet core app?

Viewed 438

I would like to sign binaries that go inside a single-file published .net core application. This is because I would like the libraries, when unpacked into %temp%\.net\%app_name%\%random_dir%, to be digitally signed. Here's my shortened version of the project file.

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
    <PublishSingleFile>true</PublishSingleFile>
    <SelfContained>true</SelfContained>
    <RuntimeIdentifier>win-x86</RuntimeIdentifier>
    <PublishTrimmed>false</PublishTrimmed>
    <PublishReadyToRun>false</PublishReadyToRun>
    <Configuration>Release</Configuration>
    <IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>    
  </PropertyGroup>

  <Target Name="SignPrePublishedFiles" AfterTargets="ComputeAndCopyFilesToPublishDirectory">
    <ItemGroup>            
      <FileToSign Include="$(OutDir)Foo.*.dll" />      
    </ItemGroup>    
    <Exec Command="jsign ~~~params removed for brevity~~~ %(FileToSign.Identity)" />
  </Target>
  
</Project>

The SignPrePublishedFiles target signs required files in the $(OutDir) dir, but the published app contains unsigned binaries. I think this is because the incorrect timing of: AfterTargets="ComputeAndCopyFilesToPublishDirectory" or incorrect folder, I assumed $(OutDir) is used for publishing. Here, I use jsign because the build runs on Linux, but the signing is done for Windows binaries.

How do you sign your published files, specifically those inside the single-file app?

1 Answers

You can sign the output dll and apphost wrapper for a project while it's in obj/ - this is what eventually gets published. Try something like this:

  <Target Name="SignIntermediates" BeforeTargets="GetCopyToOutputDirectoryItems">
    <ItemGroup>
      <FileToSign Include="$(IntermediateOutputPath)$(TargetFileName)" />
      <FileToSign Condition="'$(TargetExt)' == '.dll' And '$(OutputType)' == 'WinExe'" Include="$(IntermediateOutputPath)apphost.exe" />
    </ItemGroup>

    <Exec Command="jsign ~~~params removed for brevity~~~ %(FileToSign.Identity)" />
  </Target>

GetCopyToOutputDirectoryItems is the last public target before apphost.exe is copied and renamed to $(TargetName).exe.

Related