Поделиться через


My first demo session... - aka. "Spot the error"

Today I had my first session as DE!

I was doing a demo session on Cryptography and Security with .Net 2.0 together with my colleague Mario (who was DE previously) for a customer (actually for 3 of their developers).

Whereas he was explaining the theories of symmetric- and asymmetric algorithms and XML signing and encryption I did three live codings.

The first one was a simple demo creating a hash value with MD5- or SHA1CryptoServiceProvider:

Console.Write( "Enter Cleartext: ");
string clearText = Console.ReadLine();

SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
Byte[] hashBytes = sha1.ComputeHash(Encoding.Unicode.GetBytes(clearText));

Console.WriteLine( String.Format( "Hash Value: {0}" ,
Convert.ToBase64String(hashBytes)));

As this demo always produces equal hashes for equal cleartexts, it is easier to attack the hashed values. E.g. If a user's password hash was the same as his own he would know the cleartext of the other one (as he knows his own).

To make password hacking more difficult you could spice up the demo by including a random salt value.
Instead of hashing just the cleartext secret you would also include a random number, generated by the RNGCryptoServiceProvider object. This random value can be stored in a public way, but should be different for each user.
Although attackers know the different salts as well as the hash-values, they need to attack each user password on it's own, as the hash is dependent on the user specific salt.

In my third demo I showed how to encrypt/decrypt data using symmetric algorithms and CryptoStream objects.
Unfortunately I made a small mistake (but only a small one..) That's why my code didn't work at first...

string key = "584Af81Jasdaf(4125908";
string clearText = "Hello World!";
TripleDESCryptoServiceProvider tripledes =
new TripleDESCryptoServiceProvider();
Rfc2898DeriveBytes deriveBytes =
new Rfc2898DeriveBytes(key, 32);

// Generate random Initialization Vector
tripledes.GenerateIV();
// Derive a 16 Byte (128 Bit) Key out of the key string.
tripledes.Key = deriveBytes.GetBytes(16);

// Encryption
MemoryStream stream = new MemoryStream();
// Create CryptoStream object and pass Encryptor-ICryptoTransform object of // tripledes
CryptoStream cryptoStream = new CryptoStream (
stream, tripledes.CreateEncryptor(), CryptoStreamMode.Write
);

// Write the cleartext - unicode encoded to the stream
Byte[] dataBytes =
Encoding.Unicode.GetBytes(clearText);
cryptoStream.Write(dataBytes, 0, dataBytes.Length);

cryptoStream.Close();
stream.Close();
Byte[] cipheredBytes = stream.ToArray();

Console.WriteLine(String.Format("Ciphered Bytes: {0}",
Convert.ToBase64String(cipheredBytes)));

// Decryption
stream = new MemoryStream(cipheredBytes);
cryptoStream = new CryptoStream(
stream,tripledes.CreateDecryptor(), CryptoStreamMode.Read
);
Byte[] decryptedBytes = new byte[cipheredBytes.Length];

cryptoStream.Read(decryptedBytes, 0, decryptedBytes.Length);
cryptoStream.Close();
stream.Close();
Console.WriteLine(String.Format( "Original Value ?",
Encoding.Unicode.GetString(decryptedBytes)));

Did you spot the error? I'm sure you have.. First I was anxious that my demo would lead into a disaster :-) but unfortunately it was only a small typo!

What this demo does is using a overlayed CryptoStream to write and read data to and from an underlying stream (in this demo a MemoryStream). You can use CryptoStreams on top of any other stream, to do encryption before writing data to the stream or decrypt it after reading it from the stream.
Thereby you need to pass an ICryptoTransform object to the CryptoStream, which is created by calling the methods CreateEncryptor() and CreateDecryptor of the corresponding algorithm.

 So.. I'm glad that everything went right and I'm looking forward to doing my next session..