To summarize, this example shows that:
□ Classes belonging to a specific namespace can be located in different assemblies.
□ An assembly can contain one or more namespaces.
□ Assemblies created using different languages are transparent to each other.
Private versus Shared Assemblies
So far, all the assemblies you have seen and created are all private assemblies — that is, they are used specifically by your application and nothing else. As private assemblies, they are stored in the same folder as your executable and that makes deployment very easy — there is no risk that someone else has another assembly that overwrites yours particular and thus breaks your application.
DLL Hell
If you programmed prior to the .NET era, you've no doubt heard of (maybe even experienced) the phrase DLL Hell. Suppose that you have installed an application on your customer's computer and everything works fine until one day your customer calls and says that your application has suddenly stopped working. Upon probing, you realize that the customer has just downloaded and installed a new application from another vendor. Your application stopped working because one of the libraries (DLLs) that you have been using in your application has been overwritten by the application from the other vendor. And because your application could no longer find the particular DLL that it needs, it ceases to work.
.NET eliminates this nightmare by ensuring that each application has its own copy of the libraries it needs.
But assemblies can also be shared — that is, used by more than one application running on the computer. Shared assemblies are useful if they provide generic functionalities needed by most applications. To prevent DLL Hell, Microsoft has taken special care to make sure that shared assemblies are well protected. First, all shared assemblies are stored in a special location known as the Global Assembly Cache (GAC). Second, each shared assembly must have a strong name to uniquely identify itself so that no other assemblies have the same name.
A strong name comprises the following:
□ Name of the assembly
□ Version number
□ Public key
□ Culture
Understanding Cryptography
In the world of cryptography, there are two main types of encryption and encryption algorithms — symmetric and asymmetric.
Symmetric encryption is also sometimes known as private key encryption. With private key encryption, you encrypt a secret message using a key that only you know. To decrypt the message, you need to use the same key. Private key encryption is effective only if the key can be kept a secret. If too many people know the key, its effectiveness is reduced.
Imagine that you are trying to send a secret message to your faraway friend, Susan, using a private key. For Susan to decrypt the secret message, she must know the private key. So you need to send it to her. But if the secrecy of the key is compromised somehow (such as through people eavesdropping on your conversation), then the message is no longer secure. Moreover, if Susan tells another friend about the private key, her friend can then also decrypt the message. Despite the potential weakness of private key encryption, it is very easy to implement and, computationally, it does not take up too many resources.
Private key encryption requires that the key used in the encryption process be kept a secret. A more effective way to transport secret messages to your intended recipient is to use asymmetric encryption (also known as public key encryption). In public key encryption, there is a pair of keys involved. This pair, consisting of a private key and a public key, is related mathematically such that messages encrypted with the public key can only be decrypted with the corresponding private key. The contrary is true; messages encrypted with the private key can only be decrypted with the public key. Let's see an example for each scenario.
Before you send a message to Susan, Susan needs to generate the key pair containing the private key and the public key. Susan then freely distributes the public key to you (and all her other friends) but keeps the private key to herself. When you want to send a message to Susan, you use her public key to encrypt the message and then send it to her. Upon receiving the encrypted message, Susan proceeds to decrypt it with her private key. In this case, Susan is the only one who can decrypt the message because the key pair works in such a way that only messages encrypted with the public key can be decrypted with the private key. Also, there is no need to exchange secret keys, thus eliminating the risk of compromising the secrecy of the key.
The reverse can happen. Suppose Susan now sends a message encrypted with her private key to you. To decrypt the message, you need the public key. The scenario may seem redundant because the public key is not a secret; everyone knows it. But using this method guarantees that the message has not been tampered with and that it indeed comes from Susan. If the message had been modified, you would not be able to decrypt it. The fact that you can decrypt the message using the public key proves that the message has not been modified.
In computing, public key cryptography is a secure way to encrypt information. However, it is computationally expensive, because it is time-consuming to generate the key pairs and to perform encryption and decryption. It is usually used for encrypting a small amount of sensitive information.
To deploy an assembly as a shared assembly, you need to create a signature for your assembly by performing the following steps:
1. Generate a key pair containing a private key and a public key.
2. Write the public key to the manifest of the assembly.
3. Create a hash of all files belonging to the assembly.
4. Sign the hash with the private key (the private key is not stored within the assembly).
These steps guarantee that the assembly cannot be altered in any way, ensuring that the shared assembly you are using is the authentic copy provided by the vendor. The signature can be verified using the public key.
The following sections will show you how to perform each of these steps.
For the client application using the shared assembly, the compiler writes the public key of the shared assembly to the manifest of the client so that it can unique identify the shared assembly (only the last 8 bytes of a hash of a public key are stored; this is known as the public key token and is always unique). When an application loads the shared assembly, it uses the public key stored in the shared assembly to decrypt the encrypted hash and match it against the hash of the shared assembly to ensure that the shared assembly is authentic.
Creating a Shared Assembly
You'll better understand how to create a shared assembly by actually creating one. In this example, you create a library to perform Base64 encoding and decoding. Basically, Base64 encoding is a technique to encode binary data into a text-based representation so that it can be easily transported over networks and Web Services. A common usage of Base64 is in emails.
Using Visual Studio 2008, create a new Class Library project and name it Base64Codec
. In the default Class1.cs
, define the Helper class containing two methods — Decode()
and Encode()
:
Читать дальше