Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strong named assembly #135

Closed
tongbong opened this issue Feb 8, 2016 · 20 comments
Closed

Strong named assembly #135

tongbong opened this issue Feb 8, 2016 · 20 comments

Comments

@tongbong
Copy link
Contributor

tongbong commented Feb 8, 2016

One of our client only integrate strong named assemblies...
https://msdn.microsoft.com/en-us/library/wd40t7ad%28v=vs.110%29.aspx

It seams easy to do:
https://msdn.microsoft.com/en-us/library/xc31ft41%28v=vs.110%29.aspx

Any thought about this?

@angularsen
Copy link
Owner

I don't have any experience with that, but know what it is about and open to the idea.
I recall some pain points discussed about nuget and strong naming a long time ago, but I don't recall exactly what it was all about. Something about assembly versioning is the only thing that comes to mind.

@angularsen
Copy link
Owner

FYI. I am away all this week and will not be able to follow up before next week.

@angularsen
Copy link
Owner

Do you want to pursue this and add a PR? I don't have much time to put into this project these days unfortunately.

@angularsen
Copy link
Owner

As I thought, there is a lot of debate on whether to strong name sign open source nuget libs.

octokit/octokit.net#405 (comment)
reactiveui/ReactiveUI#43 (comment)

Based on these, I am inclined to NOT sign Units.NET. Open to discuss, naturally.

@ghost
Copy link

ghost commented Aug 22, 2016

I understand your hesitancy in strong-naming, but what has me quite confused is that it appears you have a certificate in each of the source projects, and are essentially strong-naming the source, but not the NuGet package. I would think this should be done the other way around: don't strong-name the source, so that other developers can build without having the certificate problems, but strong-name the NuGet package so that those who don't need to compile the source can simply use the NuGet package in their own strongly named solutions.

@ghost
Copy link

ghost commented Aug 22, 2016

Oops - ignore that cryptic reference to how you've already strongly named the source. I was looking at my fork.

Still, the point remains. I agree - don't sign the source. However, please sign the NuGet so that people can use it without having to compile it. :-)

@angularsen
Copy link
Owner

@bplett I'm not sure I follow. what do you mean by signing the nuget but not signing the projects?

Is this what you are referring to?
https://github.com/aspnet/Signing/blob/dev/Spec.md

@WGVDNSoftware
Copy link

I think the subject has been discussed enough in the threads you mention. I just happen to be on the side that would like to see the NuGet packages signed. I believe the biggest reason for not signing the projects is because of the hassle when people are working with the source and compiling it themselves. I'm suggesting that you could just sign the NuGet packages when you publish them and that would solve the problem for all the people who want to use the NuGet package even with strong naming in place. The way it is now, I want to use the NuGet package but can't. I have to keep a copy of the source and recompile it JUST to get the strong-naming in place.

@angularsen
Copy link
Owner

@WGVDNSoftware I absolutely get your point of view, but from what I've read of the discussions there seems to be a consensus in open source to not do strong name signing - even if it is trivial to do so. I can only refer to the discussions for the arguments, as I do not really have any experience with this myself.

@JohnCaruthers
Copy link

@anjdreas I am in a similar situation to WGVDVSoftware. I must respectfully disagree with the conclusion that you came to regarding strong naming open source projects, the information is dated. I have successfully deployed strong named open source projects, without compromising the key file. I have a great deal of experience in this arena, and I am willing to give you a detailed explanation by email, voice, and even team with you to get this done.

@ghost
Copy link

ghost commented Nov 10, 2016

It really would be GREAT if we could use the NuGets directly rather than signing our own just for the sake of strong-naming. :-)

@ghost
Copy link

ghost commented Nov 10, 2016

Btw, it would also give us more incentive to contribute to the project rather than just keep our own changes since we have to keep a local copy anyway.

@angularsen
Copy link
Owner

@jecaruthersjr I am all ears, please put forward your arguments and also please explain why the debate in the links are outdated.

I don't have any experience with consuming or creating strongly signed libs, nuget or otherwise. But I did link to quite extensive debates on repos of largely popular nugets, and the consensus at that time seemed clearly towards not strong naming the open source nugets. My conclusion was solely based on their conclusion as I did not have any new info to add to the conversation.

@angularsen angularsen reopened this Nov 10, 2016
@JohnCaruthers
Copy link

JohnCaruthers commented Nov 11, 2016

I want to start by trying to clear up and correct some of what was being said in the comments of this thread as well as the comments you referenced. If any of this information is stuff you already know, I apologize now, I have tried to compartmentalize the information so it can be easily skipped, after which I will then propose my solution.

First, people have made the assertion that strong-named assemblies have nothing to do with security. That is categorically false, they are digitally signed, which has everything to do with security.

What is a Digital Signature?
A cryptographic protocol that is used to ensure authenticity and integrity.

Do Strong-named Assemblies use Digital Signatures?
Yes, they use public key cryptography digital signatures.

How Do Public Key Cryptography Digital Signatures Work with Assemblies?

  1. The author of the assembly generates a hash, a fixed-length binary sequence, the length of the sequence is determined by the algorithm used by the author. The length of the sequence, as well as the type of algorithm used, determines the strength of the hash.
  2. The hash is then encrypted using the author's private key, this generates a digital signature for the assembly.
  3. The digital signature is attached to the assembly and distributed together with the software.
  4. When a user attempts to use the assembly in a system that requires assemblies be digitally signed the assembly is interrogated for a digital signature, if one does not exist, it is not allowed.
  5. When a digital signature is found, the user’s computer uses the same algorithm that the author used to generate the authors hash, to generate its own hash of the assembly.
  6. The user then uses the author’s public key to decrypt the author's digital signature that was included with the assembly, which produces the hash that was generated by the author.
  7. The two hashes are then compared and if they are equal the software is considered to be exactly what the author intended to distribute without modification and thus trusted to be authentic.

That being said, I’m am completely uninterested in getting into an argument or even a discussion for that matter, based on the opinions whether this type of security is secure, how much security this affords someone, or whether people should be strong-naming their assemblies, open-source or otherwise, when the only fact that matters is that Microsoft requires all assemblies to be strong named that will:

  1. Be loaded into the GAC
  2. Be referenced in another strong-named assembly

The bottom line is, right or wrong, a lot of environments, including mine, require that assemblies are loaded into the GAC, and yes, I am also fully aware of the workarounds, ILMerge, rebuilding source with our own keys, etc. These alternatives make using things like NuGet to upgrade referenced assemblies and build automation very difficult. I’ve also heard you can use hammers to drive screws, it just seems smarter to use a drill.

Another reference made was to someone complaining about new contributors becoming demotivated by having to fight to get strong-named Visual Studio projects to build, this can easily be circumvented using project build variables (www.visualstudio.com/en-us/docs/build/define/variables) to define when to use strong-naming and when not to. Furthermore, a bit of advice to anyone reading this, take it from a software engineer who knows; if fighting with a project that is not building demotivates you, I suggest getting the hell out of the software development business immediately, this isn’t for you.

Solution:

  1. Use a build server to build the project
  2. Add an Assembly Signing Build Task (using and .snk file that only exists on the build server thus, protecting it) to sign the assembly
  3. Edit the project files, and use build variables within them to only activate strong-naming during build server builds
  4. If the project builds and is signed, Package & Publish the assembly via NuGet

I skimmed over the solution on purpose. I figured you might already be bored and/or uninterested. If you are interested, and if you would like me to elaborate on one or all of the steps. Let me know, I would be happy to.

Edit: I may not have been clear about what code will actually need to change. The only changes are a few lines in the csproj file, and no extra files will need to be added either, you will store the required .snk file on the build server.

-John

@angularsen
Copy link
Owner

@jecaruthersjr I've created a draft PR for strong name signing. It seems to work, the files appear as signed and nuget updates work in the two apps I tried it in.

The only thing preventing me from pulling the trigger on this are a couple of concerns I still am not sure about, maybe you can provide some insight:

  1. There seems to be a nasty pitfall of transitive dependencies. If another lib "B" depends on a version before strong naming is introduced (ex: 3.48.0), then an application updates UnitsNet to a strong named version (ex: 3.49.0). The application will now get an exception whenever it is using "B" to interact with UnitsNet as described in this article and you can't resolve that with binding redirects. The article thus proposes the transition to strong naming be a breaking change and bump the major version of UnitsNet. I've strived to avoid breaking changes for a long time so the lib will appear stable to depend on. I'm not too keen on bumping it for the sake of SN. Is this information about transitive dependencies accurate?
  2. Strong naming introduces binding redirects, for good or worse. I am personally annoyed by all the binding redirects in an application using a large amount of nugets, but I have still not learned when or why they are introduced? I expected to see see redirects added when upgrading my app to this latest test nuget 3.48.1, but none were added? Will it only be added if there are any conflicting versions found in the solution?
  3. I have still not decided whether it is best to let the core nuget be signed, or do a separate nuget that is signed. It depends on the previous two points. What is your experience and preference here, both for consuming and producing signed nugets?

@JohnCaruthers
Copy link

JohnCaruthers commented Nov 14, 2016

@anjdreas Let me try to help out with some of these things.

Number 1
This can be a real problem depending on how versioning and updating is handled. The most elegant way I am aware of to circumvent these type of issues is to have multiple assemblies, one strong named, and one not strong named. A very large open source project, Math.Net, does this.

Number 2
I’m not a fan of binding redirects myself, thus avoid using them. Here is some more info on the subject. https://msdn.microsoft.com/en-us/library/7wd6ex19(v=vs.110).aspx Let me know if this cleared things up, and if not, we can pursue this further.

Number 3
It looks like because of number 1, you should be choosing to build a strong named and a weak named assembly.

That being said, to accomplish this I recommend, first adding Boolean build variables to the project files to isolate the strong naming properties; true, meaning strong named, and false meaning weak named, and second create 2 paths through your build server definition:

First path (weak named)

  1. Set, strong-named build variable to false
  2. Nothing else should change, just Build
    Second Path (strong named)
  3. Set, strong-named build variable to true
  4. Append .Strong or .Signed (up to you) to the assembly name
  5. Build the Assembly
  6. Sign the Assembly

Then Package and Publish both NuGet packages.

Let me know if this helped, and/or need any other help.

@angularsen
Copy link
Owner

@tongbong @jecaruthersjr @bplett @WGVDNSoftware UnitsNet.Signed 3.48.1 nuget is now out and will follow the core lib versioning from now on.

@angularsen
Copy link
Owner

angularsen commented Nov 15, 2016

If you also need the JsonSerializer and/or WinRT nugets signed, let me know. I don't add them right away because both of them are kind of niche/experimental.

@JohnCaruthers
Copy link

Thank you.

@angularsen
Copy link
Owner

Heads up on strong name signing key now being published and also changed to a new key:
#262

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants