Cryptography Using .NET: .NET Overview
|
|
1. Cryptography with C# .NET Framework. The required main namespace for this lab exercise is
System.Security.Cryptography, which provides modern cryptographic
services such as symmetric and asymmetric encryption, hashing
algorithms, and digital signatures. To see all the classes provided by
this namespace, see the System.Security.Cryptography topic in the MSDN
documentation at http://msdn.microsoft.com/library/.
2. Symmetric Encryption. In this section, we will learn how to encrypt data using symmetric
algorithms. With classes defined under the System.Security.Cryptography
Namespace, you can implement DES, RC2, Triple-DES, and Rinndael/AES
cryptosystems with the key size and block size attributes described in
the table below.
| Name |
Block Size |
Key Length (bits)
|
| DES |
64 |
56 |
| RC2 |
64 |
40, 48, 56, 64,
72, 80, 88, 96,
104, 112, 120, 128 (56-bit keys, expressed as 64-bit ) |
| Triple-DES |
64 |
Numbers |
| Rijndael (AES) |
128, 192, 256 |
128, 192, 256 |
3. Basic Encryption Example with C#.
using System;
using System.Security.Cryptography;
using System.IO;
using System.Text;
class CryptoClass
{
public byte[] Key;
public byte[] IV;
public int KeySize, BlockSize, FeedbackSize;
public CipherMode Mode;
public PaddingMode Padding;
public void Initialize()
{
Key = new byte[] { 0xFC, 0x02, 0x03, 0x04,
0x05, 0x06, 0x07, 0x08,
0x09, 0x10, 0x11, 0x12,
0x13, 0x14, 0x15, 0xAA};
IV = new byte[] { 0x99, 0x02, 0x03, 0x04,
0x05, 0x06, 0x07, 0x08,
0x09, 0x10, 0x11, 0x12,
0x13, 0x14, 0x15, 0x16};
KeySize = 128;
BlockSize = 128;
FeedbackSize = 128; This is for feedback mode only
Mode = CipherMode.ECB;
Padding = PaddingMode.Zeros;
} // end of Initialize
public string Encrypt(string plaintext) {
// get a byte array from a string of plaintext
byte[] x_plaintext = Encoding.Default.GetBytes(plaintext);
// create the encryption algorithm
SymmetricAlgorithm x_alg =
SymmetricAlgorithm.Create("Rijndael");
x_alg.KeySize = KeySize;
x_alg.BlockSize = BlockSize;
// This is for feedback mode only.
// The feedback size cannot be greater than the block size.
x_alg.FeedbackSize = FeedbackSize;
Console.WriteLine("KeySize = {0}",x_alg.KeySize);
Console.WriteLine("BlockSize = {0}",x_alg.BlockSize);
Console.WriteLine("FeedbackSize = {0}",x_alg.FeedbackSize);
// set Key
x_alg.Key = Key;
// set IV
x_alg.IV = IV;
// set padding and cipher modes
x_alg.Mode = Mode;
x_alg.Padding = Padding;
Console.WriteLine("\nMode: {0}",x_alg.Mode);
Console.WriteLine("Padding: {0}",x_alg.Padding);
// create an ICryptoTransform that can be used to encrypt data
ICryptoTransform x_encryptor = x_alg.CreateEncryptor();
// create the memory stream
MemoryStream x_memory_stream = new MemoryStream();
// create the CryptoStream that ties together the MemoryStream and the ICryptostream
CryptoStream x_cryptostream = new CryptoStream(x_memory_stream,
x_encryptor, CryptoStreamMode.Write);
// write the plaintext out to the cryptostream
x_cryptostream.Write(x_plaintext, 0, x_plaintext.Length);
// close the CryptoStream
x_cryptostream.Close();
// get the ciphertext from the MemoryStream
byte[] x_ciphertext = x_memory_stream.ToArray();
// close memory stream
x_memory_stream.Close();
// convert from array to string
string cipher_Tx =Encoding.Default.GetString(x_ciphertext);
Console.WriteLine("\n{0}\n",plaintext);
// print out the plaintext
Console.WriteLine("\n\t\tPlaintext bytes in Hex:\n");
foreach (byte b in x_plaintext)
{
Console.Write("{0:X2} ", b);
} // end of foreach
Console.WriteLine("Ciphertext:\n");
Console.WriteLine("{0}\n", cipher_Tx);
x_encryptor.Dispose();
x_alg.Clear();
return cipher_Tx;
} // end of Encrypt
} // end of CryptoClass
class CryptoApp
{
public static void Main()
{
string ciphertext;
CryptoClass c1 = new CryptoClass();
c1.Initialize();
// string of plaintext
string ptext = "We Love Cryptography Class!";
ciphertext = c1.Encrypt(ptext);
// print out the ciphertext
// ...
} // end of Main
} // end of CryptoApp
4. Program Explanation. The class CryptoClass contains two methods,
which are Initialize and
Encrypt. The Initialize method is used to generate the values of the key and
initial vector (IV). The Encrypt method receives a string of plaintext
as an argument, and then converts the string into an array of bytes.
In this simple example you will set the values of the key and IV
manually. Alternatively, the key and IV can be generated randomly using x_alg.GenerateKey() and x_alg.GenerateIV(), respectively. Since AES is a block cipher,
you need to specify the mode of
operation and block padding on the Mode and Padding members. The
following CipherMode options are available: ECB, CBC, CFB, CTS, OFB PaddingMode: Zeros, PKCS7.
To create or instantiate an encryption algorithm object (i.e., x_alg),
use the Create method of the SymmetricAlgorithm class with the
argument Rijndael as
SymmetricAlgorithm x_alg = SymmetricAlgorithm.Create("Rijndael");
You can use this object to set the key, IV, and all other
cipher attributes.
In the first stage of encryption, the class SymmetricAlgorithm
uses the ICryptoTransform interface for the cryptographic transformation
from plaintext to ciphertext or the reverse for
decryption. This interface has to be used with the CryptoStream class,
which defines a stream that links data streams to cryptographic
transformations. The CryptoStream class requires a target data stream,
the transformation to use, and the mode of the stream as the arguments. The target data
stream is an instance of the MemoryStream class, which is defined under the System.IO namespace. This class defines a stream that uses memory for
backing. In the final stage, the ciphertext is obtained from the memory
stream.
Before terminating the program, all sensitive information such as
the key, IV, or other random seed values left in the memory should be
destroyed. This can be achieved by using the Clear method for the
instances of the algorithm implementation class, and the Close method
for the Memory Stream or CryptoStream objects. The resources used by
ICryptoTransform objects can be released by the Dispose method.
|