brutaldev/StrongNameSigner

How to consume a NuGet package with signed external references?

Closed this issue · 3 comments

I'm trying to create a NuGet package for internal use. I'm using StrongNameSigner to sign the only external reference that I don't own that doesn't have a strong name. I publish it to an internal NuGet repo. So far so good.

But now I want to consume this package. The package doesn't contain the external reference, so it gets the DLL from the local NuGet cache. That file was signed while making the package. To make sure it doesn't get overwritten, I tried calling StrongNameSigner on the same file in the consuming project.

But I still get runtime errors. The exception says "Could not load file or assembly X, version Y, PublicKeyToken=null or one of its dependencies. A strongly-named assembly is required.". X has no references of its own and X.DLL in the bin folder is signed, so I don't understand what's happening.

I get why creating/consuming NuGet packages with signed external references might be hard. But is it even possible?

I've learned how to create a binlog to see all the steps while compiling a solution. As it turns out, my own DLL does reference the signed external reference. But the NuGet package just ignores the signing and references the unsigned external reference. So when I consume my own NuGet package, there is a conflict between the signed and unsigned version and the unsigned version wins.

At runtime, it can't find the unsigned version so it throws an exception and crashes.

@brinkdinges That's not going to be easy to work around. The NuGet package will reference other packages which will still be unsigned. You can try to find signed versions or re-deploy your own signed versions of external packages (once signed with StrongNameSigner). This happens quite often. Take Flurl for example:

Official (unsigned) package: https://www.nuget.org/packages/Flurl
Unofficial (signed copy): https://www.nuget.org/packages/Flurl.Signed

If you need your package to only reference signed assemblies then you can change the packages references they use to signed one because your package will not bundle the assemblies your signed with the tool.

The alternative is to just not signed anything and apply the StrongNameSigner to the project you are working on to ensure all deployed assemblies are signed even if they aren't signed packages in NuGet.

Thanks for the idea of creating an unofficial signed NuGet package. That sounds like a more streamlined version of my current solution. It might be helpful for others, though:

  1. Reference a NuGet package
  2. Build to download the DLL
  3. Sign the DLL with your own key
  4. Copy the DLL to somewhere permanent
  5. Remove the NuGet package reference
  6. Add an assembly reference to the DLL
  7. Add the DLL as content to your project
  8. Mark the content as Pack=true so it ends up in your NuGet Package
  9. Create your NuGet package

In your project file, that ends up looking like this:

<ItemGroup>
    <Reference Include="SomePackage" HintPath="..\References\SomePackage.dll">
      <Private>True</Private>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <Content Include="..\References\SomePackage.dll">
      <Pack>true</Pack>
      <PackagePath>lib\$(TargetFramework)</PackagePath>
    </Content>
  </ItemGroup>