Introduction

Strong Name (further referred to as "SN") is a
technology introduced with the .NET platform and it brings many possibilities into
.NET applications. But many .NET developers still see Strong Names as security
enablers (which is very wrong!) and not as a technology uniquely identifying
assemblies. There is a lot of misunderstanding about SNs (as we could see
in the article "Building
Security Awareness in .NET Assemblies : Part 3 - Learn to break Strong Name .NET Assemblies
") and
this article attempts to clear those up. Now let's see what SNs are, what we
can use them for and how they work.

Strong Name is a technology based on cryptographic
principles, primary digital signatures; basic idea is presented in the figure
below:

At the heart of digital
signatures is asymmetric cryptography (RSA, EL Gamal), together with hashing
functions (MD5, SHA). So what happens when we want to sign any data? I'll try to
explain what happens in the figure above.

Details

First we must get a public/private
key pair (from our administrator, certification authority, bank, application
etc.) that we will use for encryption/decryption. Then DATA (term DATA
represents general data we want to sign) is taken and run through some hashing algorithm
(like MD5 or SHA - however, MD5 is not recommended) and hash of DATA is
produced. The hash is encrypted by private key of user A and attached to
plaintext data. The DATA and attached signature are sent to user B who takes
public key of user A and decrypts attached signature where hash of DATA is stored
and encrypted. Finally user B runs DATA through the same hashing algorithm as
user A and if both hashes are the same then user B can be pretty sure that the DATA
has not been tampered with and also identity of user A is proven. But this is a
naive scenario because it's hard to securely deliver public keys over insecure
communication channels like Internet. That is why certificates were introduced
but I will not cover it here because certificates aren't used in SNs and
delivery of public key is a matter of publisher's policy (maybe I can cover
distribution of public keys, certificates and certification authorities in another article). Now let's assume that public key was delivered to user B
securely.

This process is used in the
creation of SN for .NET applications. You can translate term DATA as
assemblies and apply the same steps to them when SNs are used. But what is the
purpose and usage of this SN technology? Simple - there is the only one reason –
to uniquely identify each assembly. See section 24.3.3.4
of CLI ECMA specification where SNs are defined:

This header entry points to
the strong name hash for an image that can be used to deterministically
identify a module from a referencing point (Section 6.2.1.3).

SNs are not any security
enhancement; they enable unique identification and side-by-side code execution.

Now we know that SNs are not
security enablers. Where to use them then? We can see two scenarios where SNs
can be used:

Versioning

Authentication

Versioning solves known problem called
as "DLL hell". Signed assemblies are unique and SN solves problem with
namespace collisions (developers can distribute their assemblies even with the
same file names as shown of figure below). Assemblies signed with SNs are
uniquely identified and are protected and stored in different spaces.

In addition to collision
protection, SN should help developers to uniquely identify versions of their
.NET assemblies.

That is why when developers want
to use GAC (Global Assembly Cache) assemblies must be signed to separate
each publisher's namespace and to separate each version.

The second important feature of
Strong Names is authentication; a process where we want to ensure ourselves
about the code's origin. This can be used in many situations, such as assigning
higher permissions for chosen publishers (as will be shown later) or ensuring
that code is provided by a specific supplier.

It has been shown that signatures
and public keys can be easily removed from assemblies. Yes, that is right but
it is correct behavior even when we use digital signatures in emails or
anywhere else! Let's see how it works!

We can use some analogy from our
real life. Let's assume you are a boss of your company and you are sending an
email to your employees where new prices of your products are proposed. This
email is a plaintext and you use some non-trusted outsourcing mailing services.
Your communication can be easily monitored and your email can be easily accessed
by unauthorized persons who can change its content, for instance your prices
proposed in email.

How to solve that? The answer is cryptography,
again digital signatures that you can use to authenticate to your employees and
to verify content of your email. Simply you have to add a digital signature to
your email and then require your employees will trust just verified
emails that have your valid digital signature. Let's assume that all PKI
infrastructure is set up and working correctly. Now, when an intruder removes
the digital signature from your email, his employees will not trust them
because they can't be verified and application will alert users about this insecure
state.

The same situation is when SNs
are used. You can remove SNs from assemblies , but this makes no sense because just
as in the case of emails, assemblies without SNs can't be trusted when
environment is set up to require those digital signatures or SNs.

This is also related to another very
important point in .NET – Code Groups& Policy Levels. As in
the case of emails, when PKI is setup in a company and security policy is defined that
employees can't trust and verify emails which are not signed or where the encrypted
hash value is different from hashed plaintext content. The same can be done
with .NET Framework using the .NET Configuration tool on each machine or
by group policy for large networks.

This tool provides configuration
options for .NET Framework including Runtime Security where policy
levels and code groups can be set. Policy levels work on
intersection principle as shown in the figure below

Code groups (inside of those policy
levels) provide permission sets for applications that belong to them according
to their evidence (origin, publisher, strong name etc.). The assembly will get
those permissions based on the intersection of code groups from each policy
level applicable to it. This is a very important improvement in security
architecture and improves the traditional Windows security model that is process
centric (see figure below).

.NET introduces Code Access
Security (CAS) which is used to identify the origin of code and assign to it specific
restrictions and then make security policy more granular and protecting against
attacks such as luring attacks.

However my intention isn't to
describe CAS or Windows security internals (I can write about it in other
articles) but show SN principles. Let's move back to it!

Now we can move to the second use
for SN - administrators and developers can use SNs together with code groups to
provide assemblies with higher permissions (not the default ones that assembly
will acquire according to default .NET Framework settings). Let's see an
example! I must point out that this is just a simplified example how SN can
identify publisher, this is NOT a way to obey CLR security or how to use it
in enterprise environment. That is why please try to understand the example
as a general principle available with SNs but NOT as a design pattern!
Usage of SNs as authentication is a more complex problem and there are many
non-trivial issues when SNs are involved. But it's out of scope of this article,
so now back to the sample!

Take my sample Windows Forms
project and rebuild it and put .exe file on any share on your LAN. Then try to
start this application from this share and click on button – what happens? A security
exception is raised because application doesn't have enough privileges.

Now go to .NET Configuration tool
and add a new code group

add new code group called Test

and in the second dialog choose Strong name, click on
Import button and locate the .exe file in Debug folder of project folder and
finally assign full trust for this application

Now you have created a new code group containing just
your sample application. Now go to your network share and try to start sample
application again. And it works! Why? Because it belongs to our new code group Test
with full trust permissions.

Now remove SN from sample application (as described in his article or just
simply remove attribute [assembly: AssemblyKeyFile("KeyFile.snk")]
from AssemblyInfo.cs file), recompile and publish it on share. Try to
run it and what happens? It's not working! Why? Because assembly can't show this
strong name evidence and it belongs to the default code group (with limited
privileges) now.

It's not surprising, nothing special, no magic – just
correct usage of Strong Name technology. SNs are easy and powerful but
we have to understand how and where to use them. That is why I want to
outline some "issues" that are connected with SNs that will present all
capabilities that we can expect from SNs.

So what are the weaknesses of SNs? First we have to realize
that SNs are a lightweight version of Authenticode and they provide fast and easily
used technology to get enterprise features like versioning and authentication.
But this ease of use must be paid by something and here goes a list of
disadvantages:

It can be very hard to securely associate publisher with his
public key when certification authorities are not involved. Publisher must ship
his public key by himself and he must ensure that public key is not tampered.
Without certification authorities it's impossible to do it securely when our
products are distributed over insecure channels and there are no other ways to
verify the publisher's public key.

There is no way how to revoke public key when the private key has
been compromised. As this is easily done in case of certificates (just publish
revoked certificates on CRL, Certificate Revocation List) in case of SNs, revocation
is a nightmare. Just imagine that you as a junior security engineer has
lost USB key with your private key used to sign your assemblies. Then you'll
have to call and email your clients with newly signed assemblies, give them
your new public key and setup all environments again). There is no automatic
way like CRL, everything must be done "by hand".

Authenticode can be considered as more powerful from an enterprise
and architectural perspective. So why not use Authenticode instead of SNs?
Here are the reasons:

SNs don't require any third party (such as Verisign) to
create signatures and manage public keys. Any developer can easily create
and manage his keys (see chapter "Generate key pair with sn.exe tool" in
my free book ".NET
in Samples") without payment to any third party.

SNs can avoid network connections and PKI involvement so
applications can run and be verified even when network connections are not
available.

Authenticode certificates are not a part of assembly names
and that is why they can't separate publisher's namespaces like SNs do. Do
you remember the statement from ECMA in the beginning? That SNs should "deterministically
identify" modules and this is the most important reason. So not a security
enabler but unique identification is the primary reason for SNs! And
Authenticode is not designed for this purpose!

Conclusion

I hope this helps you understand the strong name technology in
the .NET Framework, and helped you see that it is very powerful, but with defined
limits. It is a technology that should be used appropriately.

With SNs we can uniquely identify an assembly and run
side-by-side our assemblies. Security scenarios are not recommended to be used
with Strong Names (even when it's supported by .NET Framework), just in case
you are advanced in security and working with certificates and key management.
There are many design patterns on how to use Strong Names and all this depends on
application architecture, client requirements and infrastructure settings
(Active Directory, PKI etc.).

There could be much more written about it (like usage of SNs
in large companies, problems with key distribution, etc.), but this was not
intended for this article, it was just a reaction to some misinterpretation of
this technology and the article is intended to put it right.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

My understanding is that a certificate basically is a key-pair plus metadata plus a trusted signature (or at least a certificate chain leading to a root authority). If this is so, why do we have to choose either authenticode OR SN? It seems to me it should be possible to obtain a certificate and then use the private key in the certificate to create SN assemblies. Why is it not so?

Hi! I want to know if there's any way to store a private key into an assembly. I want to encrypt the comunication between COM object and .Net object and to do this I want to use a simetric algorithm, and both objects need to know the private key.
Using Reflector tool is very easy to know the private key.
How can I protect this information inside the assembly????? Code ofuscation is the unique way to protect the key????
Thanks