I manage an open-source project and would like to sign the binaries that are released in the project's binary package. I use Visual Studio csproj
and sln
files to manage and build my project, and also distribute these files as part of the project's source packages.
How can I sign the produced binaries of my build and not have to distribute the snk
key-pair file? If I use Visual Studio to sign the assemblies, each project file now needs a copy of the key-pair in order to build. I'm not comfortable with distributing the key-pair, even if it is password protected.
Edit:
Another caveat is that some assemblies in the project grant friend access via InternalsVisibleToAttribute
, and build those friends via a project reference. Consequently, such assemblies need to use a strong name when referring to a signed assembly. However, if the key-pair is not distributed then how can end-users build the sources and maintain the project relationships? If a temporary key-pair file is used, won't the public key token of the signed assemblies change, breaking the InternalsVisibleToAttribute
references?
You should not distribute the keypair. The strongname is for verifying that the new version of assembly comes from the same publisher.
If another developer wants to branch your project they will generate their own keypair and that will effectively show that their version is not from you so that other assemblies that depend on yours will not load anymore unless they are recompiled. That's not always convenient but it protects you from someone issuing a malicious version of assembly and silently distributing it.
This is an old question, but the currently highest-voted answer is not accurate, so I figured it's worth posting a new answer.
For open source projects, Microsoft recommends checking in your private key into your repository. This is safe because strong name keys are used for identity, not security.
See here for reference: https://docs.microsoft.com/en-us/dotnet/framework/app-domains/strong-named-assemblies
Do not rely on strong names for security. They provide a unique identity only.
They also specifically address open source projects:
If you are an open-source developer and you want the identity benefits of a strong-named assembly, consider checking in the private key associated with an assembly into your source control system.
If you want security for your assemblies, then you should look into Authenticode signing: https://blogs.msdn.microsoft.com/shawnfa/2005/12/13/authenticode-and-assemblies/
Sharptooth's solution works well if the only assembly references in the code are those encoded in the project files. If your project refers to other assemblies via InternalsVisibleToAttribute
or other means where a strong-name string is required, then it is not feasible to build the repository-sources with a temporary key. Doing so will change the public key references that are present in the strong-name strings and break the code.
This is the case in my application so I needed to adopt a different approach.
I basically created a copy of the sln
and csproj
files in a separate folder heirarchy and modified the csproj
files as follows.
- Transformed all file references to links, pointing to the original sources.
- Copied and modified each AssemblyInfo.cs file to contain uses of
InternalsVisibleToAttribute
with a strong name.
- Modified each
csproj
file so that the snk
file reference is a relative path (removes the need to copy the snk
file to each project)
I first did all of this manually, but then realized that this can be automated in a straightforward manner. The first and third steps may be implemented with an XSLT, where as the second step can be implemented with a regex search/replace function.
Since I need to maintain two solutions now, it makes sense to automate this task to avoid future headaches.
The sources in the repository do not build assemblies with strong-names, which is fine, since I wouldn't want to impose any build restrictions or processes on end-users.