Symmetric Key Encryption using Rijndael and C#

kitlunchroomΤεχνίτη Νοημοσύνη και Ρομποτική

21 Νοε 2013 (πριν από 3 χρόνια και 6 μήνες)

127 εμφανίσεις

Symmetric Key Encryption using Rijndael
and C#

Published Monday, July 26, 2004 10:19 PM

Security remains the primary concern of on
-
line consumers and individuals who
wish to keep their private documents private. Cryptography is the process
associated
with keeping messages secure. The process of converting plaintext
to cipher text is called encryption and the process of reconverting the
cipher text into plaintext is called decryption. Cryptography algorithms
(ciphers) are mathematical functions used for

encryption and decryptions.


There are two types of encryption, namely asymmetric encryption and symmetric
encryption. Asymmetric encryption uses one key (the public key) to encrypt a
message and a different key (the private key) to decrypt a message, or
the
other way around. Symmetric encryption uses the same key (the secret key) to
encrypt and decrypt a message; messages encrypted with a secret key can be
decrypted only with the same secret key.


The .Net framework is developed from the ground up with se
curity in mind; the
System.Security.Cryptography namespace provides classes for

Symmetric
Encryption, Asymmetric Encryption, Hashing, Digital Signatures, Digital
Certificates and XML Signatures.


The rest of this article is going to concentrate on symmetri
c key encryption.

With the .Net framework, we have 4 choices of symmetric encryption
algorithms:



DES




Triple DES




RC2




Rijndael

DES



The Data Encryption Standard (DES) was developed by an IBM team around 1974
and adopted as a national standard in 1977. DE
S encrypts and decrypts data in
64
-
bit blocks, using a 64
-
bit key. Although the input key for DES is 64 bits
long, the actual key used by DES is only 56 bits in length. The least
significant (right
-
most) bit in each byte is a parity bit, and should be set
so that there are always an odd number of 1s in every byte. These parity bits
are ignored, so only the seven most significant bits of each byte are used,
resulting in a key length of 56 bits.



Triple DES



Triple DES is three times slower than regular DES

but can be billions of
times more secure if used properly. Triple DES is simply another mode of DES
operation. It takes three 64
-
bit keys, for an overall key length of 192 bits.
The procedure for encryption is exactly the same as regular DES, but it is
re
peated three times, hence the name Triple DES. The data is encrypted with
the first key, encrypted with the second key, and finally encrypted again
with the third key. Triple DES enjoys much wider use than DES because DES is
so easy to break with today's r
apidly advancing technology.



RC2

RC2 (Rivest Cipher) was designed by Ron Rivest

as a replacement for DES and
boasts a 3 times speed increase over DES. The input and output block sizes
are 64 bits each. The key size is variable, from one byte up to 128 bytes,
although the current implementation uses eight bytes. The algorithm is
desig
ned to be easy to implement on 16
-
bit microprocessors.

Rijndael

The National Institute of Standards and Technology (NIST) officially
announced that Rijndael, designed by Joan Daemen and Vincent Rijmen, would be
the new Advanced Encryption Standard.

The Advanced Encryption Standard (AES) is the current encryption standard,
intended to be used by the U.S. Government organisations to protect
sensitive (and even secret and top secret) information. It is also becoming a
global standard for commercial sof
tware and hardware that use encryption. It
is a block cipher which uses 128
-
bit, 192
-
bit or 256
-
bit keys. Rijndael is
very secure and has no known weaknesses.



Enter the Code:



Ok, now that we have got all of the background out of the way lets get
starte
d with the fun stuff. Lets take a look at the code, here is a simple
implementation of the Rijndael algorithm. We will start with the encryption
process first.


Encryption


private

static

string

EncryptString(
string

InputText,
string

Password)

{

// We

are now going to create an instance of the

// Rihndael class.

RijndaelManaged RijndaelCipher =
new

RijndaelManaged();


// First we need to turn the input strings into a byte array.

byte
[] PlainText = System.Text.Encoding.Unicode.GetBytes(InputText);


/
/ We are using salt to make it harder to guess our key

// using a dictionary attack.

byte
[] Salt = Encoding.ASCII.GetBytes(Password.Length.ToString());


// The (Secret Key) will be generated from the specified

// password and salt.

PasswordDeriveBytes
SecretKey =
new

PasswordDeriveBytes(Password, Salt);


// Create a encryptor from the existing SecretKey bytes.

// We use 32 bytes for the secret key

// (the default Rijndael key length is 256 bit = 32 bytes) and

// then 16 bytes for the IV (initialization

vector),

// (the default Rijndael IV length is 128 bit = 16 bytes)

ICryptoTransform Encryptor =
RijndaelCipher.CreateEncryptor(SecretKey.GetBytes(32),
SecretKey.GetBytes(16));


// Create a MemoryStream that is going to hold the encrypted bytes

MemoryStre
am memoryStream =
new

MemoryStream();


// Create a CryptoStream through which we are going to be processing our
data.

// CryptoStreamMode.Write means that we are going to be writing data

// to the stream and the output will be written in the MemoryStrea
m

// we have provided. (always use write mode for encryption)

CryptoStream cryptoStream =
new

CryptoStream(memoryStream, Encryptor,
CryptoStreamMode.Write);





// Start the encryption process.

cryptoStream.Write(PlainText, 0, PlainText.Length);





//
Finish encrypting.

cryptoStream.FlushFinalBlock();


// Convert our encrypted data from a memoryStream into a byte array.

byte
[] CipherBytes = memoryStream.ToArray();




// Close both streams.

memoryStream.Close();

cryptoStream.Close();



// Convert
encrypted data into a base64
-
encoded string.

// A common mistake would be to use an Encoding class for that.

// It does not work, because not all byte values can be

// represented by characters. We are going to be using Base64 encoding

// That is designed

exactly for what we are trying to do.

string

EncryptedData = Convert.ToBase64String(CipherBytes);


// Return encrypted string.

return

EncryptedData;

}


Decryption



Most of the logic in decryption is similar to the encryption logic.

Let’s take a quick
look at how the decryption works.


private

static

string

DecryptString(
string

InputText,
string

Password)

{

RijndaelManaged RijndaelCipher =
new

RijndaelManaged();


byte
[] EncryptedData = Convert.FromBase64String(InputText);

byte
[] Salt = Encoding.ASCII.G
etBytes(Password.Length.ToString());



PasswordDeriveBytes SecretKey =
new

PasswordDeriveBytes(Password, Salt);



// Create a decryptor from the existing SecretKey bytes.

ICryptoTransform Decryptor =
RijndaelCipher.CreateDecryptor(SecretKey.G
etBytes(32),
SecretKey.GetBytes(16));


MemoryStream memoryStream =
new

MemoryStream(EncryptedData);



// Create a CryptoStream. (always use Read mode for decryption).

CryptoStream cryptoStream =
new

CryptoStream(memoryStream, Decryptor,
Crypto
StreamMode.Read);


// Since at this point we don't know what the size of decrypted data

// will be, allocate the buffer long enough to hold EncryptedData;

// DecryptedData is never longer than EncryptedData.

byte
[] PlainText =
new

byte
[EncryptedData.Length
];



// Start decrypting.

int

DecryptedCount = cryptoStream.Read(PlainText, 0, PlainText.Length);



memoryStream.Close();

cryptoStream.Close();



// Convert decrypted data into a string.

string

DecryptedData =
Encoding.Unicode.GetString(PlainText, 0,
DecryptedCount);



// Return decrypted string.

return

DecryptedData;

}


Encrypting a file



The only difference in, encrypting a file is that we use a file stream
instead of a memory stream.


private

static

void

EncryptFile(
string

FileLocation,
string

FileDestination,
string

Password)

{

RijndaelManaged RijndaelCipher =
new

RijndaelManaged();


// First we are going to open the file streams

FileStream fsIn =
new

FileStream(FileLocation, FileMode.Open,
FileAccess.Read);

FileStream fsOut =
new

FileStream(FileDestination, FileMode.Create,
FileAccess.Write);


byte
[] Salt = Encoding.ASCII.GetBytes(Password.Length.ToString());



PasswordDeriveBytes SecretKey =
new

PasswordDeriveBytes(Password, Salt);


ICryptoTransform Encryptor =
RijndaelCipher.CreateEncryptor(SecretKey.GetBytes(32),
SecretKey.GetBytes(16));


CryptoStream cryptoStream =
new

CryptoStream(fsOut, Encryptor,
CryptoStreamMode.Write);


int

ByteData;

while

((ByteData=fsIn.ReadByte()) !=
-
1)

{


cryptoStream.WriteByte((
byte
)ByteData);

}


cryptoStream.Close();

fsIn.Close();

fsOut.Close();

}


The decrypting of a file is very similar to the encrypting of a file.


Conclusion:


The encryption/decryption sample above had a very defined purpose, bein
g
extremely easy to read and understand. While it explains how to use
encryption and gives some ideas on how to start implementing encryption in
your applications, you should add parameter checking and error handling. Wrap
calls that can potentially fail i
nto try/catch blocks, use finally blocks to
release resources if something goes wrong.