You are on page 1of 24

Encryption of FILES & WEB.

CONFIG
sections

Introduction
This article demonstrates how to use C# to encrypt and decrypt files of any type.

Background
Recently I needed to find a simple to way to encrypt and decrypt a file of any type (I
actually needed to encrypt image and text files) and any size. I found hundreds of examples
on the web, many of which just plain didn't work, or threw errors on certain file types.
Eventually I put together the following two methods using the Rijndael encryption
algorithm, they simply require that you pass them the full path to the original and target
files. They both require the System.Security, System.Security.Cryptography,
System.Runtime.InteropServices and System.Text.RegularExpressions namespaces.

Unfortunately, as I looked at so many examples on the web and actually did all this a while
ago, I do not remember which bits of code were orginally written by who. So if you
recognise some of it, many thanks, leave a comment below so that your work doesn't go
unrecognised.

Using the code


There are two methods: encryptFile and decryptFile. They both require that you pass
in the filenames and paths of the source and destination files as strings. It is important that
the user has the necessary files rights to create the encrypted file.

Collapse
Collapse Copy Code
///<summary>
/// Steve Lydford - 12/05/2008.
///
/// Encrypts a file using Rijndael algorithm.
///</summary>
///<param name="inputFile"></param>
///<param name="outputFile"></param>
private void EncryptFile(string inputFile, string outputFile)
{

try
{
string password = @"myKey123"; // Your Key Here
UnicodeEncoding UE = new UnicodeEncoding();
byte[] key = UE.GetBytes(password);

string cryptFile = outputFile;


FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);

RijndaelManaged RMCrypto = new RijndaelManaged();

CryptoStream cs = new CryptoStream(fsCrypt,


RMCrypto.CreateEncryptor(key, key),
CryptoStreamMode.Write);

FileStream fsIn = new FileStream(inputFile, FileMode.Open);

int data;
while ((data = fsIn.ReadByte()) != -1)
cs.WriteByte((byte)data);

fsIn.Close();
cs.Close();
fsCrypt.Close();
}
catch
{
MessageBox.Show("Encryption failed!", "Error");
}
}
///<summary>
/// Steve Lydford - 12/05/2008.
///
/// Decrypts a file using Rijndael algorithm.
///</summary>
///<param name="inputFile"></param>
///<param name="outputFile"></param>
private void DecryptFile(string inputFile, string outputFile)
{

{
string password = @"myKey123"; // Your Key Here

UnicodeEncoding UE = new UnicodeEncoding();


byte[] key = UE.GetBytes(password);

FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);

RijndaelManaged RMCrypto = new RijndaelManaged();

CryptoStream cs = new CryptoStream(fsCrypt,


RMCrypto.CreateDecryptor(key, key),
CryptoStreamMode.Read);

FileStream fsOut = new FileStream(outputFile, FileMode.Create);

int data;
while ((data = cs.ReadByte()) != -1)
fsOut.WriteByte((byte)data);

fsOut.Close();
cs.Close();
fsCrypt.Close();

}
}
RijndaelManaged Class
using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;

class RijndaelSample
{

static void Main()


{
try
{
// Create a new Rijndael object to generate a key
// and initialization vector (IV).
Rijndael RijndaelAlg = Rijndael.Create();

// Create a string to encrypt.


string sData = "Here is some data to encrypt.";
string FileName = "CText.txt";

// Encrypt text to a file using the file name, key, and IV.
EncryptTextToFile(sData, FileName, RijndaelAlg.Key,
RijndaelAlg.IV);

// Decrypt the text from a file using the file name, key, and IV.
string Final = DecryptTextFromFile(FileName, RijndaelAlg.Key,
RijndaelAlg.IV);

// Display the decrypted string to the console.


Console.WriteLine(Final);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}

Console.ReadLine();
}

public static void EncryptTextToFile(String Data, String FileName, byte[]


Key, byte[] IV)
{
try
{
// Create or open the specified file.
FileStream fStream = File.Open(FileName, FileMode.OpenOrCreate);

// Create a new Rijndael object.


Rijndael RijndaelAlg = Rijndael.Create();

// Create a CryptoStream using the FileStream


// and the passed key and initialization vector (IV).
CryptoStream cStream = new CryptoStream(fStream,
RijndaelAlg.CreateEncryptor(Key, IV),
CryptoStreamMode.Write);

// Create a StreamWriter using the CryptoStream.


StreamWriter sWriter = new StreamWriter(cStream);

try
{
// Write the data to the stream
// to encrypt it.
sWriter.WriteLine(Data);
}
catch (Exception e)
{
Console.WriteLine("An error occurred: {0}", e.Message);
}
finally
{
// Close the streams and
// close the file.
sWriter.Close();
cStream.Close();
fStream.Close();
}
}
catch (CryptographicException e)
{
Console.WriteLine("A Cryptographic error occurred: {0}",
e.Message);
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("A file error occurred: {0}", e.Message);
}

public static string DecryptTextFromFile(String FileName, byte[] Key,


byte[] IV)
{
try
{
// Create or open the specified file.
FileStream fStream = File.Open(FileName, FileMode.OpenOrCreate);

// Create a new Rijndael object.


Rijndael RijndaelAlg = Rijndael.Create();

// Create a CryptoStream using the FileStream


// and the passed key and initialization vector (IV).
CryptoStream cStream = new CryptoStream(fStream,
RijndaelAlg.CreateDecryptor(Key, IV),
CryptoStreamMode.Read);

// Create a StreamReader using the CryptoStream.


StreamReader sReader = new StreamReader(cStream);

string val = null;


try
{
// Read the data from the stream
// to decrypt it.
val = sReader.ReadLine();

}
catch (Exception e)
{
Console.WriteLine("An error occurred: {0}", e.Message);
}
finally
{

// Close the streams and


// close the file.
sReader.Close();
cStream.Close();
fStream.Close();
}

// Return the string.


return val;
}
catch (CryptographicException e)
{
Console.WriteLine("A Cryptographic error occurred: {0}",
e.Message);
return null;
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("A file error occurred: {0}", e.Message);
return null;
}
}
}

ENCRYPT WEB.CONFIG SECTION


using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Security.Cryptography;
using System.Web.Configuration;
using System.IO;

public partial class Default2 : System.Web.UI.Page


{
string provider = "RSAProtectedConfigurationProvider";
string section = "connectionStrings";

protected void Page_Load(object sender, EventArgs e)


{

}
protected void Button2_Click(object sender, EventArgs e)
{
Configuration confg =
WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);

ConfigurationSection confStrSect = confg.GetSection(section);

if (confStrSect != null)
{
confStrSect.SectionInformation.ProtectSection(provider);
confg.Save();

}
protected void Button1_Click(object sender, EventArgs e)
{
Configuration confg =
WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
ConfigurationSection confStrSect = confg.GetSection(section);
if (confStrSect != null &&
confStrSect.SectionInformation.IsProtected)
{
confStrSect.SectionInformation.UnprotectSection();
confg.Save();
}
}
}

ANOTHER METHOD
The classes that derive from the SymmetricAlgorithm class use a chaining mode called
cipher block chaining (CBC), which requires a key (Key) and an initialization vector (IV) to
perform cryptographic transformations on data. To decrypt data that was encrypted using
one of the SymmetricAlgorithm classes, you must set the Key property and the IV property
to the same values that were used for encryption. For a symmetric algorithm to be useful,
the secret key must be known only to the sender and the receiver.
RijndaelManaged, DESCryptoServiceProvider, RC2CryptoServiceProvider, and
TripleDESCryptoServiceProvider are implementations of symmetric algorithms.
Note that when using derived classes, it is not enough, from a security perspective, to
simply force a garbage collection after you have finished using the object. You must
explicitly call the Clear method on the object to zero out any sensitive data within the object
before it is released. Note that garbage collection does not zero out the contents of collected
objects but simply marks the memory as available for reallocation. Thus the data contained
within a garbage collected object may still be present in the memory heap in unallocated
memory. In the case of cryptographic objects, this data could contain sensitive information
such as key data or a block of plain text.
All cryptographic classes in the .NET Framework that hold sensitive data implement a Clear
method. When called, the Clear method overwrites all sensitive data within the object with
zeros and then releases the object so that it can be safely garbage collected. When the
object has been zeroed and released, you should then call the Dispose method with the
disposing parameter set to True to dispose of all managed and unmanaged resources
associated with the object.
Notes to Inheritors:

When you inherit from the SymmetricAlgorithm class, you must override the following
members: CreateDecryptor, CreateEncryptor, GenerateIV, and GenerateKey.

private static void EncryptData(String inName, String outName, byte[]


rijnKey, byte[] rijnIV)
{
//Create the file streams to handle the input and output files.
FileStream fin = new FileStream(inName, FileMode.Open, FileAccess.Read);
FileStream fout = new FileStream(outName, FileMode.OpenOrCreate,
FileAccess.Write);
fout.SetLength(0);

//Create variables to help with read and write.


byte[] bin = new byte[100]; //This is intermediate storage for the
encryption.
long rdlen= 0; //This is the total number of bytes written.
long totlen = fin.Length; //This is the total length of the input
file.
int len; //This is the number of bytes to be written
at a time.

SymmetricAlgorithm rijn = SymmetricAlgorithm.Create(); //Creates the


default implementation, which is RijndaelManaged.
CryptoStream encStream = new CryptoStream(fout,
rijn.CreateEncryptor(rijnKey, rijnIV), CryptoStreamMode.Write);

Console.WriteLine("Encrypting...");
//Read from the input file, then encrypt and write to the output file.
while(rdlen < totlen)
{
len = fin.Read(bin, 0, 100);
encStream.Write(bin, 0, len);
rdlen = rdlen + len;
Console.WriteLine("{0} bytes processed", rdlen);
}

encStream.Close();
fout.Close();
fin.Close();
}

System.Security.Cryptography Namespace
The System.Security.Cryptography namespace provides cryptographic services, including
secure encoding and decoding of data, as well as many other operations, such as hashing,
random number generation, and message authentication. For more information, see
Cryptographic Services.
Class Description
Represents the abstract base class from
Aes which all implementations of the Advanced
Encryption Standard (AES) must inherit.
Performs symmetric encryption and
decryption using the Cryptographic
AesCryptoServiceProvider Application Programming Interfaces (CAPI)
implementation of the Advanced Encryption
Standard (AES) algorithm.
Provides a managed implementation of the
AesManaged Advanced Encryption Standard (AES)
symmetric algorithm.
Represents Abstract Syntax Notation One
AsnEncodedData
(ASN.1)-encoded data.
Represents a collection of AsnEncodedData
AsnEncodedDataCollection
objects. This class cannot be inherited.
Provides the ability to navigate through an
AsnEncodedDataEnumerator AsnEncodedDataCollection object. This
class cannot be inherited.
Represents the abstract base class from
AsymmetricAlgorithm which all implementations of asymmetric
algorithms must inherit.
Represents the base class from which all
AsymmetricKeyExchangeDeformatter asymmetric key exchange deformatters
derive.
Represents the base class from which all
AsymmetricKeyExchangeFormatter asymmetric key exchange formatters
derive.
Represents the abstract base class from
AsymmetricSignatureDeformatter which all implementations of asymmetric
signature deformatters derive.
Represents the base class from which all
AsymmetricSignatureFormatter implementations of asymmetric signature
formatters derive.
Encapsulates the name of an encryption
CngAlgorithm
algorithm.
Encapsulates the name of an encryption
CngAlgorithmGroup
algorithm group.
Defines the core functionality for keys that
CngKey are used with Cryptography Next
Generation (CNG) objects.
Specifies a key BLOB format for use with
CngKeyBlobFormat Microsoft Cryptography Next Generation
(CNG) objects.
Contains advanced properties for key
CngKeyCreationParameters
creation.
Provides a strongly typed collection of
CngPropertyCollection Cryptography Next Generation (CNG)
properties.
Encapsulates the name of a key storage
CngProvider provider (KSP) for use with Cryptography
Next Generation (CNG) objects.
Encapsulates optional configuration
parameters for the user interface (UI) that
CngUIPolicy
Cryptography Next Generation (CNG)
displays when you access a protected key.
Performs a cryptographic transformation of
CryptoAPITransform
data. This class cannot be inherited.
Accesses the cryptography configuration
CryptoConfig
information.
Contains a type and a collection of values
CryptographicAttributeObject
associated with that type.
CryptographicAttributeObjectCollecti Contains a set of
on CryptographicAttributeObject objects.
Provides enumeration functionality for the
CryptographicAttributeObjectEnumer
CryptographicAttributeObjectCollection
ator
collection. This class cannot be inherited.
The exception that is thrown when an error
CryptographicException
occurs during a cryptographic operation.
The exception that is thrown when an
CryptographicUnexpectedOperationE
unexpected operation occurs during a
xception
cryptographic operation.
Defines a stream that links data streams to
CryptoStream
cryptographic transformations.
Provides additional information about a
CspKeyContainerInfo cryptographic key pair. This class cannot be
inherited.
Contains parameters that are passed to the
cryptographic service provider (CSP) that
CspParameters
performs cryptographic computations. This
class cannot be inherited.
Represents the abstract base class from
DeriveBytes which all classes that derive byte
sequences of a specified length inherit.
Represents the base class for the Data
DES Encryption Standard (DES) algorithm from
which all DES implementations must derive.
Defines a wrapper object to access the
cryptographic service provider (CSP)
DESCryptoServiceProvider version of the Data Encryption Standard
(DES) algorithm. This class cannot be
inherited.
Represents the abstract base class from
DSA which all implementations of the Digital
Signature Algorithm (DSA) must inherit.
Defines a wrapper object to access the
cryptographic service provider (CSP)
DSACryptoServiceProvider
implementation of the DSA algorithm. This
class cannot be inherited.
Verifies a Digital Signature Algorithm (DSA)
DSASignatureDeformatter
PKCS#1 v1.5 signature.
Creates a Digital Signature Algorithm (DSA)
DSASignatureFormatter
signature.
Provides an abstract base class that Elliptic
Curve Diffie-Hellman (ECDH) algorithm
ECDiffieHellman implementations can derive from. This class
provides the basic set of operations that all
ECDH implementations must support.
Provides a Cryptography Next Generation
(CNG) implementation of the Elliptic Curve
ECDiffieHellmanCng Diffie-Hellman (ECDH) algorithm. This class
is used to perform cryptographic
operations.
Specifies an Elliptic Curve Diffie-Hellman
ECDiffieHellmanCngPublicKey (ECDH) public key for use with the
ECDiffieHellmanCng class.
Provides an abstract base class from which
ECDiffieHellmanPublicKey all ECDiffieHellmanCngPublicKey
implementations must inherit.
Provides an abstract base class that
ECDsa encapsulates the Elliptic Curve Digital
Signature Algorithm (ECDSA).
Provides a Cryptography Next Generation
ECDsaCng (CNG) implementation of the Elliptic Curve
Digital Signature Algorithm (ECDSA).
FromBase64Transform Converts a CryptoStream from base 64.
Represents the base class from which all
HashAlgorithm implementations of cryptographic hash
algorithms must derive.
Represents the abstract class from which all
HMAC implementations of Hash-based Message
Authentication Code (HMAC) must derive.
Computes a Hash-based Message
HMACMD5 Authentication Code (HMAC) using the MD5
hash function.
Computes a Hash-based Message
HMACRIPEMD160 Authentication Code (HMAC) using the
RIPEMD160 hash function.
Computes a Hash-based Message
HMACSHA1 Authentication Code (HMAC) using the
SHA1 hash function.
Computes a Hash-based Message
HMACSHA256 Authentication Code (HMAC) using the
SHA256 hash function.
Computes a Hash-based Message
HMACSHA384 Authentication Code (HMAC) using the
SHA384 hash function.
Computes a Hash-based Message
HMACSHA512 Authentication Code (HMAC) using the
SHA512 hash function.
Represents the abstract class from which all
KeyedHashAlgorithm implementations of keyed hash algorithms
must derive.
Determines the set of valid key sizes for the
KeySizes
symmetric cryptographic algorithms.
MACTripleDES Computes a Message Authentication Code
(MAC) using TripleDES for the input data
CryptoStream.
Provides information for a manifest
ManifestSignatureInformation
signature.
ManifestSignatureInformationCollecti Represents a read-only collection of
on ManifestSignatureInformation objects.
Represents the abstract class from which all
MaskGenerationMethod
mask generator algorithms must derive.
Represents the abstract class from which all
MD5 implementations of the MD5 hash algorithm
inherit.
Provides a CNG (Cryptography Next
Generation) implementation of the MD5
MD5Cng
(Message Digest 5) 128-bit hashing
algorithm.
Computes the MD5 hash value for the input
data using the implementation provided by
MD5CryptoServiceProvider
the cryptographic service provider (CSP).
This class cannot be inherited.
Represents a cryptographic object identifier.
Oid
This class cannot be inherited.
Represents a collection of Oid objects. This
OidCollection
class cannot be inherited.
Provides the ability to navigate through an
OidEnumerator OidCollection object. This class cannot be
inherited.
Derives a key from a password using an
PasswordDeriveBytes
extension of the PBKDF1 algorithm.
Computes masks according to PKCS #1 for
PKCS1MaskGenerationMethod
use by key exchange algorithms.
Provides methods for protecting and
ProtectedData unprotecting data. This class cannot be
inherited.
Provides methods for protecting and
ProtectedMemory unprotecting memory. This class cannot be
inherited.
Represents the abstract class from which all
RandomNumberGenerator implementations of cryptographic random
number generators derive.
Represents the base class from which all
RC2 implementations of the RC2 algorithm must
derive.
RC2CryptoServiceProvider Defines a wrapper object to access the
cryptographic service provider (CSP)
implementation of the RC2 algorithm. This
class cannot be inherited.
Implements password-based key derivation
functionality, PBKDF2, by using a pseudo-
Rfc2898DeriveBytes
random number generator based on
HMACSHA1.
Represents the base class from which all
Rijndael implementations of the Rijndael symmetric
encryption algorithm must inherit.
Accesses the managed version of the
RijndaelManaged Rijndael algorithm. This class cannot be
inherited.
Performs a cryptographic transformation of
RijndaelManagedTransform data using the Rijndael algorithm. This class
cannot be inherited.
Represents the abstract class from which all
RIPEMD160 implementations of the MD160 hash
algorithm inherit.
Computes the RIPEMD160 hash for the
RIPEMD160Managed
input data using the managed library.
Implements a cryptographic Random
Number Generator (RNG) using the
RNGCryptoServiceProvider implementation provided by the
cryptographic service provider (CSP). This
class cannot be inherited.
Represents the base class from which all
RSA implementations of the RSA algorithm
inherit.
Performs asymmetric encryption and
decryption using the implementation of the
RSACryptoServiceProvider RSA algorithm provided by the
cryptographic service provider (CSP). This
class cannot be inherited.
Decrypts Optimal Asymmetric Encryption
RSAOAEPKeyExchangeDeformatter
Padding (OAEP) key exchange data.
Creates Optimal Asymmetric Encryption
RSAOAEPKeyExchangeFormatter Padding (OAEP) key exchange data using
RSA.
RSAPKCS1KeyExchangeDeformatter Decrypts the PKCS #1 key exchange data.
Creates the PKCS#1 key exchange data
RSAPKCS1KeyExchangeFormatter
using RSA.
Verifies an RSA PKCS #1 version 1.5
RSAPKCS1SignatureDeformatter
signature.
Creates an RSA PKCS #1 version 1.5
RSAPKCS1SignatureFormatter
signature.
SHA1 Computes the SHA1 hash for the input data.
Provides a Cryptography Next Generation
SHA1Cng (CNG) implementation of the Secure Hash
Algorithm (SHA).
Computes the SHA1 hash value for the
input data using the implementation
SHA1CryptoServiceProvider provided by the cryptographic service
provider (CSP). This class cannot be
inherited.
Computes the SHA1 hash for the input data
SHA1Managed
using the managed library.
Computes the SHA256 hash for the input
SHA256
data.
Provides a Cryptography Next Generation
SHA256Cng (CNG) implementation of the Secure Hash
Algorithm (SHA) for 256-bit hash values.
Defines a wrapper object to access the
SHA256CryptoServiceProvider cryptographic service provider (CSP)
implementation of the SHA256 algorithm.
Computes the SHA256 hash for the input
SHA256Managed
data using the managed library.
Computes the SHA384 hash for the input
SHA384
data.
Provides a Cryptography Next Generation
SHA384Cng (CNG) implementation of the Secure Hash
Algorithm (SHA) for 384-bit hash values.
Defines a wrapper object to access the
SHA384CryptoServiceProvider cryptographic service provider (CSP)
implementation of the SHA384 algorithm.
Computes the SHA384 hash for the input
SHA384Managed
data using the managed library.
Computes the SHA512 hash for the input
SHA512
data.
Provides a Cryptography Next Generation
SHA512Cng (CNG) implementation of the Secure Hash
Algorithm (SHA) for 512-bit hash values.
Defines a wrapper object to access the
SHA512CryptoServiceProvider cryptographic service provider (CSP)
implementation of the SHA512 algorithm.
Computes the SHA512 hash algorithm for
SHA512Managed
the input data using the managed library.
Contains information about the properties
SignatureDescription
of a digital signature.
Holds the strong name signature
StrongNameSignatureInformation
information for a manifest.
Represents the abstract base class from
SymmetricAlgorithm which all implementations of symmetric
algorithms must inherit.
ToBase64Transform Converts a CryptoStream to base 64.
Represents the base class for Triple Data
TripleDES Encryption Standard algorithms from which
all TripleDES implementations must derive.
Defines a wrapper object to access the
cryptographic service provider (CSP)
TripleDESCryptoServiceProvider
version of the TripleDES algorithm. This
class cannot be inherited.
Structures

Structure Description
Encapsulates a property of a Cryptography Next Generation (CNG)
CngProperty
key or provider.
DSAParamet
Contains the typical parameters for the DSA algorithm.
ers
RSAParamet
Represents the standard parameters for the RSA algorithm.
ers
Interfaces

Interface Description
Defines the basic operations of cryptographic
ICryptoTransform
transformations.
Defines methods that allow an AsymmetricAlgorithm class
ICspAsymmetricAlgo to enumerate key container information, and import and
rithm export Microsoft Cryptographic API (CAPI)–compatible key
blobs.
Enumerations

Enumeration Description
Specifies the block cipher mode to use for
CipherMode
encryption.
CngExportPolicies Specifies the key export policies for a key.

CngKeyCreationOptions Specifies options used for key creation.

CngKeyHandleOpenOptions Specifies options for opening key handles.


CngKeyOpenOptions Specifies options for opening a key.
Specifies the cryptographic operations that a
CngKeyUsages Cryptography Next Generation (CNG) key may be
used with.
Specifies Cryptography Next Generation (CNG)
CngPropertyOptions
key property options.
Specifies the protection level for the key in user
CngUIProtectionLevels
interface (UI) prompting scenarios.
CryptoStreamMode Specifies the mode of a cryptographic stream.
Specifies flags that modify the behavior of the
CspProviderFlags
cryptographic service providers (CSP).
Specifies the scope of the data protection to be
DataProtectionScope
applied by the Protect method.
Specifies the key derivation function that the
ECDiffieHellmanKeyDerivationF
ECDiffieHellmanCng class will use to convert
unction
secret agreements into key material.
Defines XML serialization formats for elliptic
ECKeyXmlFormat
curve keys.
Specifies whether white space should be ignored
FromBase64TransformMode
in the base 64 transformation.
Specifies whether to create an asymmetric
KeyNumber
signature key or an asymmetric exchange key.
Specifies the scope of memory protection to be
MemoryProtectionScope
applied by the Protect method.
Specifies the type of padding to apply when the
message data block is shorter than the full
PaddingMode
number of bytes needed for a cryptographic
operation.
Specifies most of the result codes for signature
SignatureVerificationResult
verification.

CryptoStream Class
Defines a stream that links data streams to cryptographic transformations.
Namespace: System.Security.Cryptography
Assembly: mscorlib (in mscorlib.dll)

The common language runtime uses a stream-oriented design for cryptography. The core of
this design is CryptoStream. Any cryptographic objects that implement CryptoStream can
be chained together with any objects that implement Stream, so the streamed output from
one object can be fed into the input of another object. The intermediate result (the output
from the first object) does not need to be stored separately.
You should always explicitly close your CryptoStream object after you are done using it by
calling the Close method. Doing so flushes the stream and causes all remain blocks of data
to be processed by the CryptoStream object. However, if an exception occurs before you call
the Close method, the CryptoStream object might not be closed. To ensure that the Close
method always gets called, place your call to the Close method within the finally block of a
try/catch statement.
using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;

class RijndaelSample
{

static void Main()


{
try
{
// Create a new Rijndael object to generate a key
// and initialization vector (IV).
Rijndael RijndaelAlg = Rijndael.Create();

// Create a string to encrypt.


string sData = "Here is some data to encrypt.";
string FileName = "CText.txt";

// Encrypt text to a file using the file name, key, and IV.
EncryptTextToFile(sData, FileName, RijndaelAlg.Key,
RijndaelAlg.IV);

// Decrypt the text from a file using the file name, key, and IV.
string Final = DecryptTextFromFile(FileName, RijndaelAlg.Key,
RijndaelAlg.IV);

// Display the decrypted string to the console.


Console.WriteLine(Final);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}

Console.ReadLine();
}

public static void EncryptTextToFile(String Data, String FileName, byte[]


Key, byte[] IV)
{
try
{
// Create or open the specified file.
FileStream fStream = File.Open(FileName, FileMode.OpenOrCreate);
// Create a new Rijndael object.
Rijndael RijndaelAlg = Rijndael.Create();

// Create a CryptoStream using the FileStream


// and the passed key and initialization vector (IV).
CryptoStream cStream = new CryptoStream(fStream,
RijndaelAlg.CreateEncryptor(Key, IV),
CryptoStreamMode.Write);

// Create a StreamWriter using the CryptoStream.


StreamWriter sWriter = new StreamWriter(cStream);

try
{
// Write the data to the stream
// to encrypt it.
sWriter.WriteLine(Data);
}
catch (Exception e)
{
Console.WriteLine("An error occurred: {0}", e.Message);
}
finally
{
// Close the streams and
// close the file.
sWriter.Close();
cStream.Close();
fStream.Close();
}
}
catch (CryptographicException e)
{
Console.WriteLine("A Cryptographic error occurred: {0}",
e.Message);
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("A file error occurred: {0}", e.Message);
}

public static string DecryptTextFromFile(String FileName, byte[] Key,


byte[] IV)
{
try
{
// Create or open the specified file.
FileStream fStream = File.Open(FileName, FileMode.OpenOrCreate);

// Create a new Rijndael object.


Rijndael RijndaelAlg = Rijndael.Create();

// Create a CryptoStream using the FileStream


// and the passed key and initialization vector (IV).
CryptoStream cStream = new CryptoStream(fStream,
RijndaelAlg.CreateDecryptor(Key, IV),
CryptoStreamMode.Read);

// Create a StreamReader using the CryptoStream.


StreamReader sReader = new StreamReader(cStream);

string val = null;

try
{
// Read the data from the stream
// to decrypt it.
val = sReader.ReadLine();

}
catch (Exception e)
{
Console.WriteLine("An error occurred: {0}", e.Message);
}
finally
{

// Close the streams and


// close the file.
sReader.Close();
cStream.Close();
fStream.Close();
}

// Return the string.


return val;
}
catch (CryptographicException e)
{
Console.WriteLine("A Cryptographic error occurred: {0}",
e.Message);
return null;
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("A file error occurred: {0}", e.Message);
return null;
}
}
}
Cryptography in .NET
By Suprotim Agarwal July 31, 2004
This article gives a brief overview of Cryptography and the Cryptography support
provided by the .NET Framework. I begin by introducing Cryptography and then
proceed to examine the various types of it. In particular, I review and analyze the
various cryptography algorithms and objects supported by .NET. I conclude after
proposing and briefly discussing the algorithmic technique that would work best for
you.

This article gives a brief overview of Cryptography and the Cryptography support provided
by the .NET Framework. I begin by introducing Cryptography and then proceed to examine
the various types of it. In particular, I review and analyze the various cryptography
algorithms and objects supported by .NET. I conclude after proposing and briefly discussing
the algorithmic technique that would work best for you.
Cryptography
I remember as kids, we would often play a game called 'jumble the word', where in we
would replace an alphabet of a word with another. This way, A would be replaced with C; B
with D and so on. Only someone who could understand this algorithm( in this case shift by
2), could decipher these messages and tell the word. Well in fact, this is 'Cryptography'.
Surprisingly, we often use cryptography without consciously knowing it. For example, you
may've tried to pass on a secret message to your friend using signals that only the two of
you understood, or scribbled some text whose meaning was known only to you. We have all
done that. Well....so we begin.
Cryptography is the science of scrambling meaningful characters into non-meaningful
characters so that people who do not have access to the data cannot read it. The science of
cryptography has been around for many years, even long before computers. Cryptography,
over the ages, has been an art practiced by many who have devised different techniques to
meet some of the information security requirements. The last twenty years have been a
period of transition as the discipline moved from an art to a science. With the advent of
computers, however, the science was able to produce almost unbreakable codes.
Well, Cryptography has been considered as one of the most complex aspect used by a
developer. Using cryptographic algorithms and techniques is not considered a child's play, as
it requires a high level of mathematical knowledge. Fortunately, with Microsoft .NET, newly
created classes wrap up these sophisticated algorithms into fairly easy-to-use properties
and methods. This article gives you an overview of the cryptography support that is
provided by the .NET Framework.
However lets first look into a few jargons to make you familiar with cryptography :
• Data that can be read and understood without any special measures is called
'plaintext' or 'cleartext'.
• The method of disguising plaintext in such a way as to hide its meaning is called
'Encryption'.
• Encrypting plaintext results in unreadable chunks of data called 'Ciphertext'. You use
encryption to make sure that information is hidden from anyone for whom it is not
intended, even those who can see the encrypted data.
• The process of reverting ciphertext to its original plaintext is called 'Decryption'.
• And finally 'key' is a string of bits used for encrypting and decrypting information to
be transmitted. It is a randomly generated set of numbers/ characters that is used to
encrypt/decrypt information.
Types of Cryptography
After getting familiar with the terminology, let's delve into the types of Cryptography. There
are two types of cryptography: private-key encryption and public-key encryption
Private key Encryption
Private Key encryption, also referred to as conventional or symmetric or single-key
encryption was the only available option prior to the advent of Public Key encryption in
1976. This form of encryption was used by emperors like Julius Caesar and other military
organizations to convey secret messages. This key requires all communicating parties, to
share a common key. 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
cryptography is effective only if the key can be kept secret. Despite the potential weakness
of private-key encryption, it is very easy to implement and computationally doesn't
consume excessive resources.
Lets see an example - Imagine Julius is trying to send a secret message to his army chief,
using a private key. In order for his chief to decrypt the secret message, he must know the
private key. So Julius needs to send the key to him. But if the secrecy of his key is known to
his opponents somehow , the message remains no longer secure. Moreover, if the Chief tells
his subordinate about the private key, he can then also decrypt the message.
Public-key encryption
Public key encryption algorithms are based on the premise that each sender and recipient
has a private key, known only to him/her and a public key, which can be known by anyone.
Each encryption/decryption process requires at least one public key and one private key.
Each is related to the other mathematically, such that messages encrypted with the public
key can only be decrypted with the corresponding private key.
Lets see an example - Before Julius sends a message to his chief, he needs to generate the
key pair containing the private key and the public key. The chief then freely distributes the
public key to his subordinates but keeps the private key to himself. When Julius wants to
send a message to his chief, he uses his public key to encrypt the message and then send it
to him. Upon receiving the encrypted message, the Chief proceeds to decrypt it with his
private key. In this case, he's the only one who can decrypt the message, since 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's no need to exchange secret keys, thus eliminating the risk
of compromising the secrecy of the key.
The reverse can happen as well. Suppose the Chief sends a message encrypted with his
private key to Julius. To decrypt the message, Julius need his public key. But what's the
point of that? The public key isn't a secret-everyone knows it. However, using this method
guarantees that the message hasn't been tampered with and is indeed from his chief and
not his opponents. If the message had been modified, Julius wouldn't be able to decrypt it.
I wish he was here to read all this!!!
.NET and Cryptography
.NET provides a set of cryptographic objects, supporting well-known algorithms and
common uses including hashing, encryption, and generating digital signatures. These
objects are designed in a manner that facilitates the incorporation of these basic capabilities
into more complex operations, such as signing and encrypting a document. Cryptographic
objects are used by .NET to support internal services, but are also available to developers
who need cryptographic support. The .NET Framework provides implementations of many
such standard cryptographic algorithms and objects. Similar to the ready availability of
simple authentication features within the .NET Framework, cryptographic primitives are also
easily accessible to developers via stream-based managed code libraries for encryption,
digital signatures, hashing, and random number generation. The
System.Security.Cryptography namespace in the .NET Framework provides these
cryptographic services. The Algorithm support includes:
RSA and DSA public key (asymmetric) encryption -

Asymmetric algorithms operate on fixed buffers. They use a public-key algorithm for
encryption/decryption. An example for asymmetric algorithms is the RSA algorithm which is
so named after its three inventors Rivest, Shamir, and Adleman. It is a popular public-key
algorithm - the de facto standard - for digital signatures and can be used for encryption as
well. The DSA_CSP is an implementation of the digital signature algorithm (DSA). This is a
public-key algorithm. It can be used to create and verify a digital signature.
DES, TripleDES, and RC2 private key (symmetric) encryption -

Symmetric algorithms are used to modify variable length buffers and perform one operation
for periodical data input. They use a single secret key to encrypt and decrypt data.The Data
Encryption Standard (DES) is a world-wide standard for data encryption, which was
published in the early 1970s. It is the most popular encryption algorithm. It is implemented
by the DES_CSP class. This class represents a stream where you pour in data that is
encrypted/decrypted using a single key. The Triple DES encryption algorithm operates on a
block of data three times using one key. RC2 stands for Rivest Cipher or "Ron's Code",
which is the name of its inventor. RC2 is a symmetric encryption algorithm and works with a
variable key-size. it is a block cipher, like many other .NET cryptography algorithms, that
operates on groups of bits in contrast to stream cipher algorithms.
MD5 and SHA1 hashing -

MD5 - Message Digest 5-is a one-way hash algorithm. Given variable length data as input it
always produces a 128-bit hash value. The Secure Hash Algorithm (SHA) also is a one-way
hash algorithm that produces a 160-bit hash value, which is longer than the MD5 produced
hash value.
(You must have observed the word CSP. Well CSP is a Cryptographic Service Provider. It is
the entity that performs the cryptographic computations. The CSP classes are derived from
the corresponding base classes and implement a solution for a specific algorithm. For
example, the DESCryptoServiceProvider class is derived from the DES class and implements
the digital encryption standard. You can use the provided classes or implement your own
solution. )
So many algorithms!! I am confused.
Here is a general guideline to help you decide when to use which method
Symmetric, or secret key, algorithms are extremely fast and are well suited for encrypting
large streams of data. These algorithms, both encrypt and decrypt data. While these are
fairly secure, they do have the potential to be broken given enough time, as someone could
do a search on every known key value combination. Since each of these algorithms uses a
fixed key length or ASCII characters, it is feasible that a computer program could try every
possible combination of keys and eventually stumble onto the right one. A common use of
these types of algorithms is for storing and retrieving connection strings to databases.
Asymmetric, or public key, algorithms are not as fast as symmetric, but are much harder
codes to break. These algorithms rely on two keys, one is Private and the other is Public.
The public key is used to encrypt a message. The Private key is the only one that can
decrypt the message. The public and private keys are mathematically linked and thus both
are needed for this cryptographic exchange to occur successfully. Asymmetric algorithms
are not well suited to large amounts of data due to performance. One common use of
asymmetric algorithms is to encrypt and transfer to another party a symmetric key and
initialization vector. The symmetric algorithm is then used for all messages being sent back
and forth.
Hash values are used when you do not wish to ever recover the original value and you
especially wish for no one else to discover the original value as well. Hashes will take any
arbitrary string length and hash it to a fixed set of bytes. This operation is one-way, and
thus is typically used for small amounts of data, like a password. If a user inputs a user
password into a secure entry screen, the program can hash this value and store the hashed
value into a database. Even if the database were compromised, no one would be able to
read the password since it was hashed. When the user then logs into the system to gain
entry, the password typed in is hashed using the same algorithm, and if the two hashed
values match, then the system knows the input value was the same as the saved value from
before.
Everyone Loves an Example
Everyone needs and loves a good example. After having read about the various algorithms
available, lets see an example of encrypting and decrypting files using the
System.Security.Cryptography namespace. I have used the Rijndael Managed encryption
method. The Rijndael Managed class accesses the managed version of the Rijndael
algorithm. This class cannot be inherited. The Rijndael class represents the base class from
which all implementations of the Rijndael symmetric encryption algorithm must inherit.
The hierarchy is as follows :
System.Object
System.Security.Cryptography.SymmetricAlgorithm
System.Security.Cryptography.Rijndael
System.Security.Cryptography.RijndaelManaged
To compile the following, cut and paste the code into a file, and run it in your VS.NET
// Encrypting and decrypting files using the Rijndael Managed encryption method.
using System;
using System.IO;
using System.Security.Cryptography;
class CryptoEx
{
public static void Main(string[] args)
{
if (args.Length!=1)
{
Console.WriteLine("FileName Not Entered. Specify a filename to encrypt.");
return;
}
string file = args[0];
string tempfile = Path.GetTempFileName();
// Open the file to read
FileStream fsIn = File.Open(file,FileMode.Open,FileAccess.Read);
FileStream fsOut = File.Open(tempfile, FileMode.Open,FileAccess.Write);
SymmetricAlgorithm symm = new RijndaelManaged(); //creating an instance
ICryptoTransform transform = symm.CreateEncryptor(); //and calling the CreateEncryptor
method which //creates a symmetric encryptor object.
CryptoStream cstream = new CryptoStream(fsOut,transform,CryptoStreamMode.Write);
BinaryReader br = new BinaryReader(fsIn);
cstream.Write(br.ReadBytes((int)fsIn.Length),0,(int)fsIn.Length);
cstream.FlushFinalBlock();
cstream.Close();
fsIn.Close();
fsOut.Close();
Console.WriteLine("Created Encrypted File {0}", tempfile);
fsIn = File.Open(tempfile,FileMode.Open,FileAccess.Read);
transform = symm.CreateDecryptor();
cstream = new CryptoStream(fsIn,transform,CryptoStreamMode.Read);
StreamReader sr = new StreamReader(cstream);
Console.WriteLine("Decrypted the File: " + sr.ReadToEnd());
fsIn.Close();
}
Summary :
We saw that the .NET Framework supports encryption by means of cryptographic streaming
objects based on the primitives. It also supports digital signatures, message authentication
codes (MACs)/keyed hash, pseudo-random number generators (PRNGs), and authentication
mechanisms. New or pre-standard primitives as SHA-256 or XMLDSIG are already
supported. The ready availability of such libraries is hopefully going to drive more
widespread reliance on Cryptography to fortify the security of everyday applications. Based
on our own experiences, we can confidently state that well-implemented cryptography
dramatically increases the security of many aspects of a given application.