Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Cryptography the .NET Way : Page 4

The .NET Framework classes for cryptography don't require you to become an expert mathematician or a cryptography guru. You'll find symmetric and asymmetric cryptographic providers as well as hash providers. Some of these provider classes end up calling into the unmanaged CryptoAPI library while other parts of the .NET cryptography solution are purely managed code.

CryptoStream Class
Private-key algorithms are also called block ciphers because they are used to encrypt one block of data at a time. The size of the block depends on the particular algorithm, which is normally made of a few bytes. RC2, DES, and TripleDES use 8 bytes, while Rijndael varies from a default of 16 to 24 or sometimes 32 bytes. The key determines how to cipher each block. Note that unless you take special measures, if you try to encrypt two identical blocks of text, the algorithm's output will be identical. This opens up a potential hole in the security of the algorithm that may leave your data open to attackers. For this reason, a second, not necessarily private value is used—the initialization vector (IV). By using the value of the vector, the algorithm chains together the various ciphered blocks in such a way that the next block is encrypted using the key modified by the output of the previous blocks. The IV determines how the key for the next block is created based on the previous ciphered blocks.

To encrypt using a private-key algorithm, you first make an instance of the provider class. In the code snippet below I use the Rijndael algorithm, one of the few implemented in pure managed code.

RijndaelManaged crypto; crypto = new RijndaelManaged(); byte[] Key = {...}; byte[] IV = {...}; ICryptoTransform trans; trans = crypto.CreateEncryptor(Key, IV);

Once the key and the initialization vector have been defined (both sides must agree on these values, know them, and keep them secret), you pack the parameters in a ICryptoTransform object. This object is in charge of performing the actual encryption or decryption. The CreateEncryptor and CreateDecryptor methods just return an instance properly configured for the action to accomplish.

To complete the operation, you can then either call the TransformBlock method or, better yet, use the CryptoStream class.

The class defines a Stream object that links data streams to cryptographic transformations. You initialize CryptoStream passing another stream object that acts as the data provider. The input stream can be any stream that is, in turn, linked to some physical data. For example, it can be a file stream or a network stream. Internally, the class transparently performs any tasks that are needed to encrypt and decrypt.

FileStream file; file = new FileStream(fileName, FileMode.Open); CryptoStreamMode mode = CryptoStreamMode.Write; CryptoStream enc; enc = new CryptoStream(file, trans, mode);

The CryptoStream class constructor takes three arguments:

  • The input Stream as an instance of any Stream-based class,
  • The ICryptoTransform object, which performs the decryption and encryption. You obtain the crypto transformer directly from the class that wraps the cryptographic service provider.
  • The working mode. It is a value picked from the CryptoStreamMode enumeration—Read or Write. In read mode the class decrypts, and in write mode it encrypts.
Using CryptoStream has a couple of advantages:

  • First, you don't need to know much about the algorithm being used under the hood. You must know the agreed key and vector. You must create a decryptor or an encryptor object and pass it to the stream class. The hard work with cipher blocks and output chaining—which is indeed necessary—takes place within the .NET class.
  • Second, in the .NET Framework you can build a pile of Stream objects and have each work on top of the other. In the code snippet above you read the content of a file with the FileStream class and, by simply linking the stream to the cryptographic stream, you read or write its encrypted contents! No other effort is required on your end. You use the instance of the CryptoStream class as you would do with any other Stream class, including the original FileStream class. Whenever you call Read the text is automatically and transparently decrypted; whenever you call Write the text is silently encrypted and used with the configured key and initialization vector.
If you have an application that manages disk files through streams, with an extra step you can have it use encryption too. If you don't have such an application, but plan to write a similar one, the pair FileStream and CryptoStream is extremely powerful. CryptoStream inherits from Stream so it features all the I/O methods of streams.

Listing 1 shows a complete application that creates an encrypted text file and decrypts it. The example makes use of the Rijndael algorithm and the CryptoStream class.

Hash Algorithms
Hash functions are a fundamental piece in cryptography today. They map arbitrary binary data to small arrays of a fixed length called hash values. Hash functions are commonly used with digital signatures and for verifying data integrity.

Hash functions exploit some mathematical principles by means of which small changes to the data result in completely different and unpredictable hash values. Here's an example of how to compute a hash value.

byte[] input = new byte[100]; // Fill the input buffer somehow byte[] output; SHA1CryptoServiceProvider sha; sha = new SHA1CryptoServiceProvider(); output = sha.ComputeHash(input);

The code necessary to generate a hash value doesn't change much if you use other hash algorithms. You simply change the name of the class.

Hash values represent an effective way to verify the integrity of the data being received over a potentially insecure channel. For example, you can attach a hash value to a string of text you're sending. Your code calculates the hash value based on the contents that you want to send. When data comes back you can compare the hash value of received data to the original hash value. If the two values match, then the data is intact; otherwise, the necessary conclusion is that something tampered with your data. ASP.NET widely exploits just this mechanism.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date