views:

552

answers:

3

How are assemblies resolved in .net. I mean, how is an assembly with a fully qualified name resolved. I am confused about the public/private key tokens and strong naming. Thanks

EDIT: I have also read about delayed signing and stuff like that. Do people really use it? (Has anyone actually used delay signing) Who generates the key to sign an assembly. I am sorry if I am asking too many questions. But, I am confused about this whole thing.

+1  A: 

Assemblys resolving can involve a number of steps, depending on where the assembly it is trying to load is (GAC, application base folder, sub folders, or another folder away from your base application folder).

This is a good article about how you can specify where .Net looks for your assemblies. MSDN Article

If you want the runtime to resolve an assembly that is not stored in your application base folder or the GAC then you will need to register for the AppDomain event which is raised when it can't find the assembly. You would then react on that event by checking if the file exists in your other location and then return it using Assembly.LoadFrom(thePath).

Just to add to this answer further is this cracking link that should sum up the whole strong naming with keys very nicely for you: Strong Naming - keys etc..

Any questions from this, just ask!

Ataris22
Who generates the key to sign an assembly?
P.K
+1  A: 

The following article on MSDN should help you out:

http://msdn.microsoft.com/en-us/library/yx7xezcf(VS.71).aspx

Assembly resolution in .NET can be fairly complex, as assemblies can be located in a variety of locations including the GAC, colocated with the executing assembly, shadow copied, etc. The general process is called the Fusion process, and ensures that proper security measures are met when loading assemblies.

jrista
+4  A: 

Strong naming is used together with a "public key token" to produce an assembly full display name (mscorlib, version=2.0.0.0, Culture=neutral, PublicKeyToken=b4778,.....). This enables us have multiple versions of the same assembly side-by-side within the same application directory.

A public key token (and hence, string naming technique) also allows the .NET loader to detect whether anybody has tampered with your assembly contents since you distributed it. This is true because when you sign an assembly with your "private token", the compiler will generate a hash value which it embeds into the assembly metadata that describes the public portion of your "private token". The loader can then use this value to determine whether or not your assembly was modified.

Concerning resolving assemblies, there are a few basic things to consider:

  • Probing The loader attempts to locate assemblies using a basic directory "probing" technique. This means that it will try to locate "MyAssembly.dll" (for instance) in the application's startup directory, if not there, then in subdirectories below that. If probing fails to locate "MyAssembly.dll", then the AppDomain's AssemblyResolve event is fired.

  • Machine/User/System configuration The machine.config, user.config and system.config are configuration files stored locally on the system which one can use to change the behavior of the assembly resolver on a "machine", "user" or "system"-wide setting.

  • Publisher Policy One can use the "<assemblyIdentity>" XML token in your application's configuration file (for instance, "MyApp.exe.config") to point to resolver to a certain version of an assembly or to load an assembly from a different location.

  • Custom resolution Handle the "AssemblyResolve" event of the AppDomain. This event is raised whenever an assembly could not be resolved via "traditional" methods

By far the least complicated mechanism is to handle the "AssemblyResolve" event.

To summarize, the resolver looks in the current directory or the Global assembly cache, processes policy and then finally allows custom resolution.

Mike J
"allows the .NET loader to detect whether anybody has tampered with your assembly contents..." didn't quite get that.
P.K
Sure. Basically when you compile your assembly with a strong name hash value (you can also use the commandline utility sn.exe), the hash value gets written to the assembly's metadata that describes its version, culture, name and token value. When the loader loads your assembly, it checks if your assembly has a public key token and if so, runs the same hash algorithm over your assembly, compares it with what's in the assembly metadata and refuses to load the assembly if they differ.That's how the loaded detects "tampering". It's very limited as you can see, but sufficient for now.
Mike J
On the surface, it looks like a way to protect our .NET code. But alas, the excitement wears off quickly and you will soon realize that obfuscation is the next best thing.
Mike J
And I don't get the part of "..it looks like a way to protect our .NET code". I always thought that signing an assembly ensures that we are using the assembly that was originally intended for use. (But is there a situation when this might fail?) and not for protecting source code (for which obfuscation serves the purpose).
P.K
Yes signing does ensure we only load assemblies we built with (it also allows side-by-side versioning and sharing our assembly globally via the Global Assembly Cache). Also, publisher policy allows us to "redirect" a reference from one version of an assembly to a different version.Are there situations where it would fail? Sure. but if referenced assemblies fail to load, usually it's related to path location, invalid version of the assembly or security permission problems (such as loading from a shared network drive).
Mike J