不签名.NET 程序集有什么问题吗?

我的一个同事非常热衷于签署集会。他真的什么都想签。即使我们使用的程序集来自微软,没有签署,他会采取源代码,签署它,然后要求其他开发人员使用他的副本而不是。

我可以理解对程序集进行签名背后的基本思想: 确保某个特定程序集不会被某个狡猾的黑客破坏。因此,如果我们是一家软件开发公司,我们应该在发布之前签署我们的组装。我们的客户。

然而,我们在这里主要是为自己开发 Web 应用程序,我只是不明白为我们使用的每一个组件签名有什么意义。

我错过了什么吗?

23333 次浏览

I agree it seems like a bit of a waste. It's really needed to ensure the file is what you think it is (and hasn't been tampered with). But if you trust the confines of your own network security and web server, then signing your web assemblies seems like a redundant step.

But maybe that's my small-business experience talking. If you're talking about a mission-critical online banking website, then sign away.

Signing assemblies that are used within a trusted environment sounds like overkill to me.

An interesting point on signed assemblies is that they are slightly slower to load than unsigned assemblies, as they must be cryptographically verified.

In order to sign an assembly, any assemblies it depends upon must also be signed. My guess is that this contributes to your colleague's desire to sign everything -- the compiler is demanding it.


EDIT Since writing this answer you can see both the pro and against camp have roughly equivalent support. There clearly isn't a right answer here.

The point that compelled this edit though is that nowadays we take so many open source libraries from NuGet, and many of them are not signed at all. If you wanted to sign your assembly, you'd need to have any dependencies signed too. Many of the open source libraries that are signed have the private keys used for signing publicly available in their source repositories.

As with everything there are trade-offs to be made. In my experience of working in private environments, the benefits of signing are mostly theoretical (or academic, as @user289100 mentions), unless you're concerned about government agencies modifying your code in which case you need to be paranoid about so many levels of your infrastructure that signing would seem like a small amount of effort. Otherwise the amount of challenges that cascade out of having to sign everything just don't seem worth it. However your environment may have different requirements, or you may be a masochist!

See also Teun D's answer for information on challenges related to versioning assemblies when using strong names.

Has your colleague given you any indications as to why he likes to sign assemblies? One advantage to signing that hasn't been discussed here yet is that only signed assemblies can be put in the GAC (i.e. be shared across managed processes), but the downsides do seem to outweigh the upsides from my (admittedly inexperienced) perspective.

Your anecdote about self-signing Microsoft code seems particularly suspect to me. If MS didn't sign the code, there's probably a reason, right? And by signing it, you're taking responsibility for it when you didn't write it - another opportunity for the future to bite you.

Another thing about signing an assembly is, that one can't inject incorrect one in place of yours (also - yourself by an accident). In example, if you create a program that refers to an assembly Foo.dll, version 1.0, someone can create the an assembly, with the same version, and replace yours, when you sign your library, it won't be possible (at least I don't think it's easily possible).

Signatures are only necessary if the assemblies are placed in the GAC, nothing else. Signed assemblies do not prevent someone to mess with them. A hacker can still strip of the signature and any other code that checks for the signature.

Think about doing it if you're going to ship something and/or actually have a reason to do it. In every other case, it's just hassle. I'd ask your workmate what he actually gets out of doing this.

I've encountered signed assembly-itis before and it's a pain in the posterior, especially when you consider the amount of people who have little to no knowledge of signing assemblies, what it's for and how to do it. It's just another thing you shouldn't have to concern yourself with unless absolutely necessary.

One additional point: signing your assemblies breaks backward compatibility over versions. Your references all start to include version numbers and versions with other version numbers are considered non-compatible. This hinders upgrading to newer versions of distributed assemblies.

In my opinion, you should only code-sign assemblies if you see some concrete gain from it:

  • if you deploy to environments where untrusted people might touch your assemblies
  • in certain plug-in models, where you want to use the certificate as evidence for upgrading the trust
  • if your code should be callable from other signed code (a project like, say log4net, justifiably signs their code to be widely usable; they messed up hugely in compatibility by losing their secret key a few years ago, another risk of code-signing).
  • if you want to deploy to the GAC

I've taken advantage of non-signed assemblies to get around issues before and in academic settings shown people why it's important. I replaced a DLL file that was unsigned (again in an academic setting) with one I made with the same name, same signatures, and used .NET Reflector to copy and paste the original code, but in mine I emailed user names and passwords that were being passed in before calling 'real' code.

If signed, you can make a signature match, but not replace. Contrary to what Zippy says, there will be a run-time compliation error.

Signing assemblies is never overkill. It takes 30 seconds. It's like saying locking your doors is overkill if you live in the country. If you want to gamble with your belongings, go ahead, leave it open. It only takes one security breach to get fired. It only takes 30 seconds to sign an assembly and there's no business case not to. The performance impacts is negligable.

You need to sign your assembly when it's used in a deploy-from-the-web ClickOnce XBAP.

In addition, all referenced assemblies will need to be signed as well.

We sign our assemblies because there are times when we get errors like the following (this one is from testing, but can occur when running the application):

System.IO.FileLoadException : Could not load file or assembly 'Latitude.Platform.Core, Version=1.0.5871.22518, Culture=neutral, PublicKeyToken=7926214d13e12325' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)


TearDown : System.IO.FileLoadException : Could not load file or assembly 'Latitude.Platform.Core, Version=1.0.5871.22518, Culture=neutral, PublicKeyToken=7926214d13e12325' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

We'd found that Visual Studio gets it wrong sometimes and runs old code.

If you want an error if you are running old code, then sign your assemblies.

If you are writing a nuget package, please sign your assemblies. Unsigned assemblies is awkward for us who want to make sure we're running the latest version of our code. I can't fix Visual Studio. All I can do is detect that Visual Studio got it wrong. So please, sign your nuget assemblies.