Strong naming

Strong naming refers to signing an assembly with a key, producing a strong-named assembly. When an assembly is strong-named, it creates a unique identity based on the name and assembly version number, and it can help prevent assembly conflicts.

The downside to strong naming is that .NET Framework on Windows enables strict loading of assemblies once an assembly is strong named. A strong-named assembly reference must exactly match the version of the loaded assembly, forcing developers to configure binding redirects when using the assembly:

<configuration>
   <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
         <dependentAssembly>
            <assemblyIdentity name="myAssembly" publicKeyToken="32ab4ba45e0a69a1" culture="neutral" />
            <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>
         </dependentAssembly>
      </assemblyBinding>
   </runtime>
</configuration>

When .NET developers complain about strong naming, what they're usually complaining about is strict assembly loading. Fortunately, this issue is isolated to .NET Framework. .NET 5+, .NET Core, Xamarin, UWP, and most other .NET implementations don't have strict assembly loading, which is the main downside of strong naming.

One important aspect of strong naming on .NET Framework is that it's viral: a strong-named assembly can only reference other strong-named assemblies. If your library isn't strong named, then .NET Framework apps and libraries that need strong naming can't use it.

The benefits of strong naming on .NET Framework are:

  1. The assembly can be referenced and used by other strong-named assemblies.
  2. The assembly can be stored in the Global Assembly Cache (GAC).
  3. The assembly can be loaded side by side with other versions of the assembly. Side-by-side assembly loading is commonly required by applications with plug-in architectures.

Strong naming has no benefits on .NET Core/5+. C# compiler produces CS8002 warning for strong-named assemblies referencing non-strong named assemblies. It is fine to suppress this warning for libraries that target .NET Core/5+ only.

Create strong named .NET libraries

You should strong name your open-source .NET libraries if their targets include .NET Framework or .NET Standard. Strong naming is not required for libraries that target .NET Core/5+ only.

Note

This guidance is specific to publicly distributed .NET libraries, such as .NET libraries published on NuGet.org. Strong naming is not required by most .NET applications and should not be done by default.

✔️ CONSIDER strong naming your library's assemblies.

✔️ CONSIDER adding the strong naming key to your source control system.

A publicly available key lets developers modify and recompile your library source code with the same key.

You shouldn't make the strong naming key public if it has been used in the past to give special permissions in partial-trust scenarios. Otherwise, you might compromise existing environments.

Important

When the identity of the publisher of the code is desired, Authenticode and NuGet Package Signing are recommended. Code Access Security (CAS) should not be used as a security mitigation.

✔️ CONSIDER incrementing the assembly version on only major version changes to help users reduce binding redirects, and how often they're updated.

Read more about versioning and the assembly version.

❌ DO NOT add, remove, or change the strong naming key.

Modifying an assembly's strong naming key changes the assembly's identity and breaks compiled code that uses it. For more information, see binary breaking changes.

❌ DO NOT publish strong-named and non-strong-named versions of your library. For example, Contoso.Api and Contoso.Api.StrongNamed.

Publishing two packages forks your developer eco-system. Also, if an application ends up depending on both packages the developer can encounter type name conflicts. As far as .NET is concerned they are different types in different assemblies.