Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Signed the assemblies. #3

Closed
wants to merge 1 commit into from

8 participants

@cedricbrasey

Created a new sn key and signed the assembly. Please message me and i'll send you the password or regenerate the SN. What ever is easier

@cedricbrasey cedricbrasey Signed Assembly
Created a new sn key and signed the assembly
7047f7c
@Haacked
Collaborator

Why this change?

@cedricbrasey
@Haacked
Collaborator

/cc @davidebbo I thought the official WebActivator package was signed.

@Haacked Haacked closed this
@Haacked Haacked reopened this
@Haacked
Collaborator

Whoops, I almost merged that on accident. :)

@davidebbo
Owner

This came up before, and then triggered the gigantic forum discussion. But in the end, it was never signed.

Not sure we really want to re-open this can of worm. Lots of people are using WebActivator, so I wouldn't want to do this lightly.

To summarize, signing makes it more difficult to use assemblies A and B in your project if they are built against different versions of WebActivator. NuGet tries to solve that using binding redirects, but that doesn't work in all cases.

@Haacked
Collaborator

Yeah, i think the real solution is the improved handling of strong naming in NuGet. We've talked about having NuGet have the ability to auto-sign assemblies in a package if that's the only way it can work (aka the target project is signed).

@davidebbo
Owner

Indeed we have. Many times! And this WebActivator specific thread is probably not the place to discuss this. :)

OTOH, I do wonder how much actual harm would happen is WebActivator was signed, since it is only used in Web projects, and binding redirects tend to work pretty well there.

Typical case where binding redirects don't work is unit tests. Since it runs under its own exe (e.g. xunit.exe), the binding redirect doesn't affect it. However, I don't think anyone would ever expect WebActivator logic to execute in the context of unit tests, so that might be a non-issue here.

@cedricbrasey

I hadn't realised that this was such a heated debate and to be honest i just don't get wht this is such an issue, but that just me. So does this mean that there will or won't be an offical signed WebActivator version?

@davidebbo
Owner

One potential approach is to sign it and use a version that never changes, to avoid some of the issues. So basically it'll always have assembly version 1.0 (the Win32 version can move up as it's not used for resolution). Apparently, JSON.net does something similar.

Let me get more feedback on this idea first.

@davidebbo
Owner

It’s actually a pretty tough situation. If the latest version becomes signed, then it will in fact break the world because of all the existing packages that use the unsigned version.

Seems the only way out is:

  • Create a new NuGet package with a different name, different assembly name and different namespace. i.e. Use WebActivator.Signed throughout. This is necessary to avoid conflicts when both are used.
  • Unpublish the unsigned WebActivator to stop new apps from using it.

Then many apps will end up using both packages side by side, which will probably work, but is an ugly situation.

Maybe someone will come up with a better plan...

@Haacked
Collaborator

Why does that break everybody if the latest becomes signed?

@davidebbo
Owner

Scenario:

  • Package A uses unsigned WebActivator (as is the case for lots of packages today)
  • Package B uses signed WebActivator (as most new package would if we switch)
  • You write an app that uses A and B, and things blow up, because NuGet will move up to the newer (signed) version, and A.dll won't be able to bind to it.

It won't be a super common situation at first, but give it a few months for new packages to start using signed WebActivator, and things will blow up all over the place.

Root of the problem is that you can't have binding redirects that redirect from simple name to strongly named assembly. Binding redirect is only to move up version for a given signature.

@Haacked
Collaborator

Ah, but I assume Package A's reference to WebActivator (since it's not strongly named) will be a simple by name reference and will thus use signed WebActivator just fine.

In other words, I didn't think you need binding redirects for a non-sn assembly. I guess I've never tried it with a non-SN -> SN assembly.

@davidebbo
Owner

We should double check, but I'm pretty sure it won't bind.

@davidebbo
Owner

I just tried it to be sure and confirmed that it does not work:

Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly 'ClassLibraryBindTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

So unless there is a trick to make it bind (other than AssemblyResolve event which is a non-starter), then we're out of luck here.

@Haacked
Collaborator

bummer.

@cedricbrasey
@bradwilson

Right, you can't "binding redirect" to something which doesn't have the same fundamental identity (and signed vs. non-signed changes the fundamental identity).

@davidebbo
Owner

@cedricbrasey Can you clarify what you mean by 'enforcing a strongname policy'? Related to WebActivator, NuGet, or .NET in general?

But note that more and more people are trying to move away from strong naming, so it indeed would likely not be a popular proposal :)

@cedricbrasey
@davidebbo
Owner

This is probably not the right place to discuss the general signing vs not signing issue, but we can certainly discuss it relating to WebActivator.

First, I'd like to understand the scenario better. Since that is the root of the issue, why is it a rule that you have to strong name your assembly? Note that even NuGet packages that are signed are often done with non-secret keys. i.e. they're signed for convenience, but that provides no security whatsoever. So it seems like a pretty arbitrary rule which may have been set by people who don't have full understanding of the security implications (I know you don't always control what clients say...).

Note that in the OSS world, what you may view as unethical is actually perfectly acceptable, and very much part of how things work. There is absolutely nothing wrong with taking the code and redistributing it as long as it doesn't violate the license (which is very permissive!).

Note that you would not be able to put your package on NuGet and call it WebActivator, so it would have to be a different name.

As far as getting updates and fixes, git solves that pretty nicely. All you have to do is fork the repo, and later pull changes to get updates.

I'm not saying this is a great approach, but it is certainly more feasible than you make it sound.

That being said, I could conceivable own a spin off package called WebActivator.Signed, but I am a bit worried about user confusion.

@Andrew-Webb

Ok, I get the subtleties. I recommend introducing StrongWebActivator or SignedWebActivator or WebActivatorEx, whatever. Maybe add some functional improvements to make it more enticing. Packages should be encouraged to use it, but they can still use basic WebActivator. The hope is that over time the use of WebActivator will drop to zero.

The thing is, shipping code should be strongly named. Code Analysis will tell you to do so. And I've seen first-hand the downside of not doing so... crashing code on certain users' machines. The diagnosis came when the team signed their assemblies... and then the CLR's loader told them that the images were corrupt (on these certain machines, for whatever reason). There are no doubt other benefits as well. See Microsoft's documentation about why assemblies should be signed.

@cedricbrasey
@mahara

On the subtleties, I wonder why it has be to have a new name. Why not just using a new (major) version? Users still can choose to install legacy (unsigned) versions, if needed. And as a user, I wonder why I would be confused if it made that way.

@davidebbo
Owner

Most of the arguments in favor of signing can be refuted, and for the most part have been in this forum thread. But that can be a religious debate, and this is not the place for it (that thread is).

The only reason I see to sign to sign WebActivator is to unblock those who are forced to use signing, as long as it can be done with minimal impact to those who are not.

So anyway, let's keep this thread focused on how we can achieve this, rather on further arguments about whether strong naming is good/bad, as we'll just have to agree to disagree on that point :)

@mahara: I think things would blow up if it was just a new version, per my previews comment. Does that make sense?

So unfortunately, I don't think we can avoid renaming the Package, the assembly and the namespace for things to go smoothly.

But then the problem is that it will be hard to make anyone use the new package. One thing that might work is to have a new version of WebActivator (say 2.0) that does nothing other than depend on the new package. This way, people who just install WebActivator in a new project would effectively get the new one. But I need to convince myself that this is indeed not a breaking change, as this can be pretty subtle, and it's easy to overlook scenarios.

As for the new name, @Andrew-Webb's ideas are possible options. Any other ideas? Naming is hard :)

@Andrew-Webb

WebActivator2

WebActivatorForEveryone

SublimeWebActivator

WebActivator2013

@davidebbo
Owner

A couple other things we didn't cover:

  • The private key would be committed to the repo, since we're not doing this for any 'security' reasons. We want to make sure that anyone can build it.
  • We would keep the assembly version fixed (e.g at 1.0), to avoid binding redirect hell. The goal here is not to GAC it so Side by Side is not a scenario.
@mahara

@davidebbo: I'm not sure I understand correctly the scenario you presented. Are you saying that an app (probably you meant "an unsigned app") can reference both unsigned and signed WebActivator assemblies? That kinda new to me.
In my apps, I sign my apps so that I can't use any unsigned assemblies; only signed ones. Probably, most apps would be unsigned.

@davidebbo
Owner

@mahara: the app wouldn't directly reference both, but would end up doing it indirectly by referencing A and B, and that would blow up. That's why the name can't stay the same. And yes, this only applies to unsigned apps, which is most of them out there.

@mahara

OK. So now suppose this new WebActivator package, named WebActivatorEx (or whatever), created. Would it be required to have its "WebActivator" namespace changed or not in case when applied to that scenario?

@davidebbo
Owner

Namespace needs to change too.

@nberardi

@cedricbrasey I would venture to say that even though web activator isn't as popular as JSON.NET it is popular enough to where strong naming would cause major issues for many referencing projects when the version changes and they didn't specifically point to a specific version in their references http://coderjournal.com/2012/04/json-net-strong-naming-and-nuget-woes/

The issue isn't so much the strong naming, it is that when the version changes it has a ripple effect that breaks every referencing project, except for the authors that were the most anal about setting an exact reference version.

What really disappoints me about these posts asking for strong naming, is that the poster always thinks that causing major disruptions in the NuGet ecosystem is some how easier than them downloading the source and strong naming it them self.

I do think that NuGet needs to be a little more smart about strong named assemblies though. And make separate folders in the lib for strong names. "net45s" for example. Also the ability to search for only strong named assemblies on the site would be a nice thing for people like @cedricbrasey. That way everything is still up to the package publisher and people that have to support companies that are strong-name happy can just search for strong-named assemblies.

@mahara

@nberardi
I don't think there's really any disadvantage for a framework library assembly being signed; the same with .NET Framework library assemblies, and other framework libraries I used in my signed apps. Both unsigned and signed apps would still be able to consume them. However, when a framework library weren't signed, any signed apps wouldn't be able to consume at all, and that really matters. And I consider WebActivator, JSON.NET, or any other libraries in NuGet as framework libraries.
So positioning is important here: a framework library, or just a (sample) app, that not need to be signed.

@nberardi

@mahara what happens if you have the following relation in NuGet package A references signed assembly in package B. signed assembly in package B is updated and the version changes, but package A is not updated?

Hint: package A no longer works, because package B was signed. So package A has to be recompiled and published before it will work again.

@cedricbrasey

Am I missing something here but isn't JSON.net signed? The point that I'm trying to make is that if I write an application that uses version 4.5 of JSON.net (only for example here) I expect and demand that my application only work with this versioned dependency. As this is what was tested and signed off by QA. What I don't want is for another application to decided that what I actually want is version 4.6... 9 times out of 10 there is a good reason why I've bound to a specific version (functionality, bug fix, etc).

I did a little checking and looking at the top 30 packages (ordered by downloads) in nuget:-
19 packages deploy binaries
11 packages deploy javascript/transforms

out of the 19 packages
18 are assemblies (i.e. project referenced items)
1 is a tool

out of the 18 assemblies
16 are strong named.
2 are not strong named.

Even nuget.core is signed...

Why not have nuget enforce a strong name policy and then use the GAC for assembly storage? After all wasn't that the point behind it's creation? My wish is that WebActivator gets bumped to v2.0.0.0 and signed.

@cedricbrasey

@nberardi

Wasn't the GAC created to resolve this (amongst other issues) scenario?

@mahara

@nberardi
Surely, it would matter. And it would also be debatable over choosing whether to use file version or assembly version. Let's say, for the sake of this discussion, I'd choose not to update it just for the sake of being up-to-date, and not a necessity.
But try looking at this issue from a larger perspective. Put it this way to make it easier: What would happen if I didn't sign my critical LOB app assemblies, and thus they were altered deliberately, and caused a serious security breach for the whole system.
Now tell me, given these two choices: What would really matter here?

@nberardi

@cedricbrasey JSON.NET is doing that now but they just started last year after they created a horrible mess in JSON.NET that still hasn't been cleaned up. They fixed the mess by using semVer, which basically means that with each release they don't change the version number of the assembly, so that they aren't constantly breaking all referencing projects. See my blog post that I referenced for more information about what was going on then.

Secondly the GAC was created in a different world almost 13 years ago. Where most applications were installed on a desktop, and there was no such thing as a global package service for sharing of packages like NuGet. I think you have to take a deep dive on how version numbers effect signed packages and then combine that with the knowledge of how NuGet references packages. Because signing assemblies isn't bad, but when combined with the reference system in NuGet it becomes a whole different beast that you guys are failing to see.

@nberardi

@mahara lets not play what if games, because you probably store your signing key with your source like most other users and most open source projects as @davidebbo alluded to earlier, so all that somebody would have to do is modify your code set the same version number as you are using in production and the breach would occur anyways.

Hell I could do this with JSON.NET, copy it to your LOB app, and suddenly be copying out all your web service calls and proprietary information going back and forth. Strong naming is not a security mechanism, it has never been and never will be, and using it as such just leads to false assumptions like the one you are making about your LOB app.

@dsplaisted

@cedricbrasey Another application wouldn't affect which version of a library you get. But you might use two different third party libraries that were compiled against two different versions of (for example) Json.NET. NuGet's versioning policy does as well as you can do I think. See this series of blog posts: http://blog.davidebbo.com/2011/01/nuget-versioning-part-1-taking-on-dll.html

@mahara

@nberardi
LOL... you started the "what-if" game, and then ended it yourself... :D
Yes, I've read @davidebbo concern over where to store the signing key. My next question would then be: Where do MS store their signing key for the whole .NET Framework assemblies? Do they ever distribute it publicly ([assembly: AssemblyKeyFile(@"f:\dd\tools\devdiv\EcmaPublicKey.snk")])? And then back to your question: Is there any reason to store the signing key you mentioned for public access?

To certain degrees, yes, I agree that strong naming is not a security mechanism. Especially, when the should-not-be-disclosed signing key made available to public for access. What can I say? :)

Perhaps, MS should completely remove the following guideline page as it's misleading and/or inaccurate, don't you think so?
CA2210: Assemblies should have valid strong names (http://msdn.microsoft.com/en-us/library/ms182127.aspx)
Visual Studio 2012
...

Rule Description

This rule retrieves and verifies the strong name of an assembly. A violation occurs if any of the following are true:
• The assembly does not have a strong name.
• The assembly was altered after signing.
• The assembly is delay-signed.
• The assembly was incorrectly signed, or signing failed.
• The assembly requires registry settings to pass verification. For example, the Strong Name tool (Sn.exe) was used to skip verification for the assembly.

The strong name protects clients from unknowingly loading an assembly that has been tampered with. Assemblies without strong names should not be deployed outside very limited scenarios. If you share or distribute assemblies that are not correctly signed, the assembly can be tampered with, the common language runtime might not load the assembly, or the user might have to disable verification on his or her computer. An assembly without a strong name has from the following drawbacks:
• Its origins cannot be verified.
• The common language runtime cannot warn users if the contents of the assembly have been altered.
• It cannot be loaded into the global assembly cache.

Note that to load and analyze a delay-signed assembly, you must disable verification for the assembly.
...

@nberardi

@mahara No reason to remove CA2210, because it is not on by default. Choose "Microsoft Managed Recommend Rules" and see if you find CA2210. It isn't there.

@bradwilson
CA2210: Assemblies should have valid strong names (http://msdn.microsoft.com/en-us/library/ms182127.aspx)

If only there were a way to tell stupid & pointless FxCop rules to fuck off... :-p

@davidebbo
Owner

I put the current proposal on https://github.com/davidebbo/WebActivator/wiki/Signing-WebActivator, so we have a basis of discussion.

@mahara

@nberardi
Nah, I was just kidding about the idea. I put a bit of sarcasm in there... :D
Certainly, the rule is created for reasons explained there. If there's any argument against it, then such arguments should be directed directly to the rule maker a.k.a. MS.

@mahara

@davidebbo
Great! Thanks for the detailed proposal. It makes this (and the other one) discussion getting closer to an executable decision.
I'm fine with WebActivatorEx for the name. Seems like "Ex" suffix is a standard protocol in MS world... :D

@davidebbo
Owner

I pushed a signed WebActivatorEx package to NuGet: http://nuget.org/packages/WebActivatorEx/. Can you please give it a try?

Let's call it experimental at this point, as I need more feedback about it being what we really want before starting to advertise it for general use. Thanks!

@cedricbrasey
@Andrew-Webb

Thank you @davidebbo - it works for me (tested in VS Express 2012 for Web).

Will you be naming it "WebActivatorEx" in NuGet (currently it appears as a second "WebActivator")?

Will you be changing the NuGet description of the original WebActivator to point people to the new version?

Thanks again for: your open-mindedness, your accommodation of us strong-namers, and for your work.

@davidebbo
Owner

The package is named WebActivatorEx, but I made the display name be WebActivator. Once we get more confidence that this will all work without breaking people transitioning, the plan is to unlist the old one so only the new one shows up.

@leastprivilege leastprivilege referenced this pull request in IdentityModel/Thinktecture.IdentityModel.45
Closed

Assembly from NuGet is not signed #50

@davidebbo
Owner

Closing this since assembly is now signed.

@davidebbo davidebbo closed this
@mahara

@davidebbo: Thanks for this!

@Bringer128 Bringer128 referenced this pull request in dvsekhvalnov/jose-jwt
Closed

Strong naming #5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 13, 2012
  1. @cedricbrasey

    Signed Assembly

    cedricbrasey authored
    Created a new sn key and signed the assembly
This page is out of date. Refresh to see the latest.
View
9 TestLibrary/TestLibrary.csproj
@@ -32,6 +32,12 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
+ <PropertyGroup>
+ <SignAssembly>true</SignAssembly>
+ </PropertyGroup>
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>WebActivator.snk.pfx</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
@@ -54,6 +60,9 @@
<Name>WebActivator</Name>
</ProjectReference>
</ItemGroup>
+ <ItemGroup>
+ <None Include="WebActivator.snk.pfx" />
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
View
BIN  TestLibrary/WebActivator.snk.pfx
Binary file not shown
View
9 TestWebApp/TestWebApp.csproj
@@ -1,5 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <SignAssembly>true</SignAssembly>
+ </PropertyGroup>
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>WebActivator.snk.pfx</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -121,6 +127,9 @@
<Name>WebActivator</Name>
</ProjectReference>
</ItemGroup>
+ <ItemGroup>
+ <None Include="WebActivator.snk.pfx" />
+ </ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
View
BIN  TestWebApp/WebActivator.snk.pfx
Binary file not shown
View
2  WebActivator.sln
@@ -1,6 +1,6 @@

Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2012
+# Visual Studio 2010
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C2257462-7F5F-4C80-B04B-3D48026B109C}"
ProjectSection(SolutionItems) = preProject
Local.testsettings = Local.testsettings
View
BIN  WebActivator.snk.pfx
Binary file not shown
View
7 WebActivator/Properties/AssemblyInfo.cs
@@ -23,7 +23,12 @@
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("3bc078bd-ade4-4271-964f-1d041508c419")]
-[assembly: InternalsVisibleTo("WebActivatorTest")]
+[assembly: InternalsVisibleTo("WebActivatorTest, PublicKey=00240000048000009400000006020000002400005253413100040000010" +
+ "00100a5c110967144cbbc9d6b7575ebd7ec573baf87095e9a57432ef4c2" +
+ "f3a1310b748ec315aba53565d854da9e72eca971a0a75b20c779d5e7c38" +
+ "8c51f9fbc5ec47ae77a9f200553388c06b36c6eb8d45c04d9171b1af166" +
+ "ed8f246c2ea023793ae540a0026f9f0a7539105a0c0519f0e56700f04a7" +
+ "ae2a919e6af7dbb528f507ec1")]
// Version information for an assembly consists of the following four values:
//
View
7 WebActivator/WebActivator.csproj
@@ -34,6 +34,12 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
+ <PropertyGroup>
+ <SignAssembly>true</SignAssembly>
+ </PropertyGroup>
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>WebActivator.snk.pfx</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
@@ -61,6 +67,7 @@
<None Include="Properties\WebActivator.nuspec">
<SubType>Designer</SubType>
</None>
+ <None Include="WebActivator.snk.pfx" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
View
BIN  WebActivator/WebActivator.snk.pfx
Binary file not shown
View
BIN  WebActivatorTest/WebActivator.snk.pfx
Binary file not shown
View
9 WebActivatorTest/WebActivatorTest.csproj
@@ -34,6 +34,12 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
+ <PropertyGroup>
+ <SignAssembly>true</SignAssembly>
+ </PropertyGroup>
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>WebActivator.snk.pfx</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="System" />
@@ -60,6 +66,9 @@
<Name>WebActivator</Name>
</ProjectReference>
</ItemGroup>
+ <ItemGroup>
+ <None Include="WebActivator.snk.pfx" />
+ </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Something went wrong with that request. Please try again.