top button
Flag Notify
    Connect to us
      Site Registration

Site Registration

Cryptography And .NET Framework - Part 1

0 votes
349 views

Introduction

Security is key consideration for many applications. Providing authentication and authorization services to your application is just one part of the overall security. What about the data that is being used and transferred in the application? That is where cryptography comes into picture. Cryptography is a huge topic by itself. In this series of articles I am going to confined our discussion only to .NET Framework and cryptographic classes provided by it.

Why use Cryptography?

Many times application provide security features such as login forms and role based security. However, what if someone intercepts the data that is being flown over the network? What if someone plays with the data that is being transmitted over the network? What if someone opens SQL Server database that is storing passwords? Cryptography provides solution to such questions. Using .NET Cryptographic classes you can encrypt the data that is being flown in your system or network and then decrypt when you want authenticated user to modify or read it. In short Cryptography provides following features:

  • Protect data being transferred from reading by third parties
  • Protect data being transferred from any modification
  • Make sure that data is arriving from the intended location

Types of Cryptographic classes

The overall Cryptographic classes available in .NET framework can be classified in four categories:

  • Classes that deal with secret key encryption (also called as Symmetric Cryptography)
  • Classes that deal with public key encryption (also called Asymmetric Cryptography )
  • Classes that deal with digital signatures (also called cryptographic signatures)
  • Classes that deal with cryptographic hashes

All the cryptography related classes can be found in System.Security.Cryptography namespace.

Secret Key Encryption

In Secret Key Cryptography the data being protected is encrypted using a single secret key. This key is known only to sender and receiver. The sender encrypts the data using the secret key. The receiver decrypts the data using the same secret key. It is very important to keep the key secret otherwise anybody having the key can decrypt the data.

.NET Framework provides following classes to work with Secret Key Cryptography:

  • DESCryptoServiceProvider
  • RC2CryptoServiceProvider
  • RijndaelManaged
  • TripleDESCryptoServiceProvider

Public Key Encryption

Unlike secret key encryption, public key encryption uses two keys. One is called public key and the other is called as private key. The public key is not kept secret at all where as private key is kept confidential by the owner of that key. The data encrypted by private key can be decrypted only using its corresponding public key and data encrypted using public key can be decrypted using its private key. Naturally, in order to encrypt the data being transmitted you need to use public key. This data can be decrypted only with the corresponding private key.

.NET Framework provides following classes to work with public key encryption:

  • DSACryptoServiceProvider
  • RSACryptoServiceProvider

Digital Signatures

Digital signatures are used to verify identity of the sender and ensure data integrity. They are often used along with public key encryption. Digital signature work as follows:

  1. Sender applies hash algorithm to the data being sent and creates a message digest. Message digest is compact representation of the data being sent.
  2. Sender then encrypts the message digest with the private key to get a digital signature
  3. Sender sends the data over a secure channel
  4. Receiver receives the data and decrypts the digital signature using public key and retrieves the message digest
  5. Receiver applies the same hash algorithm as the sender to the data and creates a new message digest
  6. If sender's digest and receiver's digest match then it means that the message really came from the said sender.

The classes DSACryptoServiceProvider and RSACryptoServiceProvider are used to create digital signatures.

Hashes

Hash algorithms create a fixed length output for a given variable length data. If somebody changes the original data even slightly then the hash generated will be different than original hash. They are often used with digital signatures.

Some of the classes in .NET that deal with hashes are:

  • SHA1Managed
  • MD5CryptoServiceProvider
  • MACTripleDES

Random Number Generators

While working with cryptography classes many times you need to generate cryptographic keys. Random number generators are used for this purpose. .NET provides a class called RNGCryptoServiceProvider to generate such random numbers.

In the next article we will see how the secret key encryption can be done using the relevant classes.

posted Dec 9, 2016 by Shivaranjini

  Promote This Article
Facebook Share Button Twitter Share Button LinkedIn Share Button


Related Articles

Introduction

In the Part 2 of this series we learnt to use Secret Key Encryption techniques using Triple-DES algorithm. More often to transfer data encrypted via secret key encryption public key encryption is used. This puts one extra layer of security over the data being transferred. From Part 1 we know that public key encryption consists of two keys - public key and private key. Data encrypted by public key can be decrypted only by the corresponding private key and vice a versa. One of the most popular algorithm for encrypting and decrypting data using this technique is RSA. The acronym RSA stands for Rivest, Shamir, and Adelman who are the inventors of the technique. The .NET framework provides a class called RSACryptoServiceProvider that encapsulates this algorithm. In this article we are going to learn how to use this class to secure your data.

Developing a class for encryption and decryption

Many developers don't want to go into the internals of Cryptography. They simply need a quick and easy way to secure their data. So we are going to develop such reusable class that will do the job of encrypting and decrypting for us.

We will create a class called PublicKeySecurityHelper which will have two methods - Encrypt and Decrypt. In addition we will also create a helper class called MyRSAInfo. This class will simply store certain pieces of data (such as public key and private key).

Here, is the complete code of the class.

Imports System.Security.Cryptography
Imports System.IO
Imports System.Text

Public Class PublicKeySecurityHelper
    Public Function Encrypt(ByVal strData As String) As MyRSAInfo
        Dim myrsa As New MyRSAInfo
        Dim p As CspParameters = New CspParameters
        p.Flags = CspProviderFlags.UseMachineKeyStore
        myrsa.Parameters = p
        Dim rsa As RSACryptoServiceProvider = 
	New RSACryptoServiceProvider(p)
        Dim data() As Byte = 
	rsa.Encrypt(Encoding.Unicode.GetBytes(strData), False)
        myrsa.PublicKey = rsa.ToXmlString(False)
        myrsa.PrivateKey = rsa.ToXmlString(True)
        myrsa.Data = data
        Return myrsa
    End Function
    Public Function Decrypt(ByVal myrsa As MyRSAInfo) As Byte()
        Dim rsa As RSACryptoServiceProvider = 
	New RSACryptoServiceProvider(myrsa.Parameters)
        rsa.FromXmlString(myrsa.PublicKey)
        Dim data() As Byte = rsa.Decrypt(myrsa.Data, False)
        Return data
    End Function
End Class
Public Class MyRSAInfo
    Public PublicKey As String
    Public PrivateKey As String
    Public Parameters As CspParameters
    Public Data() As Byte
End Class

Let's dissect the code step by step:

Encrypting data

  • First we import the required namespaces. Especially System.Security.Cryptography is important one because it contains our core class RSACryptoServiceProvider
  • We create a method called Encrypt() that accepts the string to be encrypted and returns an instance of a class called MyRSAInfo
  • MyRSAInfo is our custom class defined at the bottom of the code. It consists of four public members - PublicKey, PrivateKey, Parameters and Data
  • The PublicKey and PrivateKey members store the generated public key and private key respectively.
  • The Parameters variable is of type CspParameters. This is used to automatically generate public and private keys and reuse them later on.
  • The Data is an array of bytes and stores the encrypted version of the data
  • Inside the Encrypt() method we create an instance of CspParameters class and set its Flag property to CspProviderFlags.UseMachineKeyStore. This enumerated value specifies from where the key information should be picked up i.e. from default key container or from machine level key store.
  • Then we create new instance of RSACryptoServiceProvider class passing the CspParameters instance.
  • We then call Encrypt() method of RSACryptoServiceProvider class and pass data to be encrypted. Since this parameter is byte array we convert our string into byte array using GetBytes() method. The second parameter of the method indicates whether to use OAEP padding (true) or PKCS#1 v1.5 padding (false). The former can be used only on Windows XP machines and hence we pass False. The Encrypt() method of RSACryptoServiceProvider class returns a byte array that contains encrypted version of the data.
  • Finally, we fill all the members of MyRSAInfo class and return to the caller. Note how we call ToXmlString() method first passing False and then passing True to get public and private keys respectively.

Decrypting data

  • In order to decrypt the data we create a method called Decrypt() that accepts an instance of MyRSAInfo class. This instance must be the one returned by the Encrypt() method explained earlier.
  • Inside Decrypt() method we create an instance of RSACryptoServiceProvider class again passing the same CspParameters.
  • We then call FromXmlString() method of the RSACryptoServiceProvider class and pass the public key generated before.
  • Finally, we call Decrypt() method of RSACryptoServiceProvider class and pass the encrypted data. The second parameter of Decrypt method has the same significance as that of the corresponding parameter of Encrypt() method

Download

Complete source code along with a sample usage is available for download with this article (see top).

Summary

Public key encryption is a secure way to transfer data over networks. The fact that the private key is not sent in unsafe manner makes it more secure and robust. This technique is used in Secure Socket Layer (SSL) or HTTPS based web sites. The .NET framework class RSACryptoServiceProvider allows you to generate public and private keys, encrypt and decrypt data. In the next article we will learn about digital signatures. Stay tuned!

READ MORE

Introduction

In the Part 1 we learnt the basics of Cryptography and related .NET Framework classes. In this article we are going to see how to work with Secret Key Encryption using Triple-DES algorithm.

Triple-DES

The System.Security.Cryptography namespace contains a class called TripleDESCryptoServiceProvider that provides Triple-DES encryption to your data. DES stands for Data Encryption Standard and the word triple is used because it encrypts the original data thrice.

The secret key encryption needs two things to encrypt the data:

  • A secret key
  • An initialization vector

The encryption algorithms employ use a chaining technique to encrypt the data. In this technique the entire data to be encrypted is divided in smaller blocks. The previously encrypted block of data is used to encrypt the current one and the process repeats.

The Initialization Vector (IV) serves as a seed that is used to encrypt and decrypt the first block of bytes. This ensures that no two blocks of data produce the same block of encrypted text.

For using TripleDESCryptoServiceProvider the encryption key must be of 24 bytes and the initialization vector must be of 8 bytes.

Example of using TripleDESCryptoServiceProvider class

In this example we will first create a class called SecurityHelper that will help us encrypt and decrypt string data. Here is the code for the class:

Imports System.Security.Cryptography
Imports System.IO
Imports System.Text
Public Class SecurityHelper
    Public Key() As Byte
    Public IV() As Byte
    Public Function Encrypt(ByVal strData As String) As Byte()
        Dim data() As Byte = ASCIIEncoding.ASCII.GetBytes(strData)
        Dim tdes As TripleDESCryptoServiceProvider = 
	New TripleDESCryptoServiceProvider
	If Key Is Nothing Then
		tdes.GenerateKey()
		tdes.GenerateIV()
		Key = tdes.Key
		IV = tdes.IV
	Else
		tdes.Key = Key
		tdes.IV = IV
	End If
        Dim encryptor As ICryptoTransform = 
	tdes.CreateEncryptor()
        Dim ms As New MemoryStream
        Dim cs As CryptoStream = 
	New CryptoStream(ms, encryptor, CryptoStreamMode.Write)
        cs.Write(data, 0, data.Length)
        cs.FlushFinalBlock()
        ms.Position = 0
        Dim result(ms.Length - 1) As Byte
        ms.Read(result, 0, ms.Length)
        cs.Close()
        Return result
    End Function
    Public Function Decrypt(ByVal data() As Byte) As String
        Dim tdes As TripleDESCryptoServiceProvider = 
	New TripleDESCryptoServiceProvider
        tdes.Key = Key
        tdes.IV = IV
        Dim decryptor As ICryptoTransform = 
	tdes.CreateDecryptor()
        Dim ms As New MemoryStream
        Dim cs As CryptoStream = 
	New CryptoStream(ms, decryptor, CryptoStreamMode.Write)
        cs.Write(data, 0, data.Length)
        cs.FlushFinalBlock()
        ms.Position = 0
        Dim result(ms.Length - 1) As Byte
        ms.Read(result, 0, ms.Length)
        cs.Close()
        Return ASCIIEncoding.ASCII.GetString(result)
    End Function
End Class

Let's examine the code step by step:

  • We create a class called SecurityHelper with two functions Encrypt() and Decrypt(). The former accepts the string to be encrypted and returns encrypted form of the string as a byte array. The later accepts the encrypted data in the form of a byte array and returns decrypted data as a string.
  • The class has two public variables of byte array type. They are used to assign the secret key and initialization vector.
  • In the Encrypt() function we first convert the string to be encrypted into a byte array using GetBytes() method.
  • We then create an instance of TripleDESCryptoServiceProvider class
  • The key and initialization vector can be supplied externally by you or TripleDESCryptoServiceProvider class can generate one automatically for you. If user has not supplied key and IV we call GenerateKey() and GenerateIV() methods respectively. These methods create a random key and IV automatically for you. We assign the generated key and IV to public variables Key and IV.
  • Then we call CreateEncryptor() method of TripleDESCryptoServiceProvider class and collect its return value in a variable of type ICryptoTransform. The ICryptoTransform interface defines the basic operations of cryptographic transformations.
  • We then create a memory stream. The encrypted data will be put inside this stream.
  • We also create a CryptoStream and pass the memory stream and the encryptor created above.
  • Next, we write the data to be encrypted to the CryptoStream object. The CryptoStream object stores the encrypted version of the data in the supplied memory stream.
  • Finally, we read the memory stream for encrypted data. Put that data in an array of bytes and return it to the caller.

Decryption process is similar but follows reverse path. The only major difference between encryption and decryption code is that in case of decryption we call CreateDecryptor() method of TripleDESCryptoServiceProvider class.

Summary

In this article we saw how TripleDESCryptoServiceProvider class can be used to encrypt and decrypt string data. With little or no modification you can reuse the class for your own requirements. Some common uses of this algorithm can be - storing passwords in database, string confidential data such as bank account numbers etc. in database. In the example above we used memory stream to put our data but you can also use FileStream to save the data to a disk file. In the next article we will see how to use public-key encryption.

READ MORE

Introduction

In previous parts of this series (Part 1Part 2 and Part 3) we saw various techniques of encrypting the data. In this part we are going to learn how to ensure that data coming to you has not been tampered with during the transfer. The technique that we will be using is hash. Hash values allow us to verify the integrity of data. The hash value of received data can be compared to the hash value of data that was sent to check if the data is tampered.

.NET Framework classes for creating hashes

.NET Framework provides following main classes to work with hashes:

  • SHA1Managed
  • MD5CryptoServiceProvider
  • MACTripleDES

Since SHA1 is now a broken algorithm, we will use MD5CryptoServiceProvider to generate hash values.

Example

We are going to create a helper class that will help us create and verify hash values using MD5 algorithm. The class contains two methods - GetHash() and VerifyHash(). The former accepts string whose hash value is to be generated and returns the computed hash as a byte array. The later accepts the message as it was received and the hash generated previously and returns true if the message is not altered during transmit otherwise returns false.

public class MD5HashHelper
{
public byte[] GetHash(string message)
{
byte[] data;
data=System.Text.UTF8Encoding.ASCII.GetBytes(message);
MD5CryptoServiceProvider md5=new MD5CryptoServiceProvider();
return md5.ComputeHash(data,0,data.Length);
}
public bool VerifyHash(string message, byte[] hash)
{
byte[] data;
data=System.Text.UTF8Encoding.ASCII.GetBytes(message);
MD5CryptoServiceProvider md5=new MD5CryptoServiceProvider();
byte[] hashtemp=md5.ComputeHash(data,0,data.Length);
for(int x = 0; x < hash.Length;x++)
{
if (hash[x] != hashtemp[x])
{
return false;
}
}
return true;
}
}

Let's dissect the code step by step:

  • We first need to import System.Security.Cryptography namespace in your class
  • The GetHash() accepts string whose hash value is to be generated and returns the computed hash as a byte array.
  • Inside the function we used UTF8Encoding class and get aa byte representation of the string to be transfered.
  • We then create an instance of MD5CryptoServiceProvider class and call its ComputeHash by passing the byte created above to it.
  • The ComputeHash() function generates the hash for the given data and returns another byte array that represents the hash value of the data.
  • The VerifyHash() function accepts the message as it was received and the hash generated previously and returns true if the message is not altered during transmit otherwise returns false.
  • Inside this function we again use UTF8Encoding class and generate byte representation of the received message.
  • We then compute hash for this data using the same ComputeHash() method of MD5CryptoServiceProvider class.
  • Finally, we run a for loop and check each and every byte of original hash value and the hash we generated above. If both the hash values are matching we can conclude that the data is not tampered.

Download

Complete source code along with a sample usage is available for download with this article (see top).

Summary

In this example we saw how to ensure data integrity using MD5 hashing algorithm. In the next article on the series we will learn to generate digital signatures.

READ MORE

Networks can be configured to be so incredibly redundant now - for reasonable prices - that there is no excuse for a data center not to achieve five nines (99.999%) of availability.

But what about the servers and applications? Why spend so much time up front configuring the network to make sure it doesn't fail, and then deploy an application to a single server?

Sure, there are ways to make sure individual servers have some redundancy to minimize failures -- things like RAID1, RAID5, or RAID10 (redundant array of inexpensive disks) which will protect against a disk drive failure (and I highly recommend this type of configuration for all production servers - and preferably the use of hardware RAID vs. software RAID). But what happens if a file gets corrupt on the RAID array? Or a recent configuration change brings the application down? Or a newly released patch conflicts with other settings and causes problems? Well, in these situations the server will go down and the application(s) hosted on that server will be offline.

A good monitoring and alerting process will allow the system administrator to detect and address these issues quickly, but still there will be some level of downtime associated with the issue. And depending on the type of issue, even the best system administrator might not be able to immediately resolve the issue - it may take time. Time during which your application is unavailable and you may be losing business due to the site interruption.

So, what can you do?

A great option - and one that has recently become more affordable - is to host your application on a webfarm. A webfarm consists of two or more web servers with the same configuration, and that serve up the same content. There are special switches and processes involved that allow each of these servers to respond to a request to a single location. For example, say we have two servers - svr1.orcsweb.com and svr2.orcsweb.com - that have 100% the same configuration and content. We could configure a special switch* to handle traffic that is sent to www.orcsweb.com and redirect the traffic to either of these nodes depending on some routing logic. All clients visiting the main URL (in this case www.orcsweb.com) have no idea whether this is a single server - or ten servers! The balancing between nodes is seamless and transparent.

[*note: There is also software that could handle the routing process but experience and test have shown that these types of solutions are generally not as scalable, fast, or efficient as the hardware switch solutions]

The routing logic can be a number of different options - most common are:

  • Round-robin: Each node gets a request sent to it "in turn". So, node1 gets a request, then node2 again, then node1, then node2 again.
  • Least Active: Whichever node shows to have the lowest number of current connects gets new connects sent to it. This is good to help keep the load balanced between the server nodes.
  • Fastest Reply: Whichever node replies faster is the one that gets new requests. This is also a good option - especially if there are nodes that might not be "equal" in performance. If one performs much better than the other, why not send more requests there?

In any of these scenarios the switch will also detect if a node were to fail. So, if svr1.orcsweb.com was taken offline for maintenance - or it had a critical failure - the switch would detect that and only send traffic to svr2.orcsweb.com. And since the clients always access the site via the main URL (not the node names) they have no idea that one of the nodes is down - the application continues to serve client requests seamlessly.

Besides high-availability (continuing to satisfy requests during a failure), a webfarm also gives an application a higher level of scalability - the ability to handle more and more load. If load increased on the application to the point where performance started to degrade, more nodes could be added to the webfarm (again, without clients noticing), giving the ability to handle potentially unlimited levels of traffic (just keep adding nodes!).

Of course there are a lot of factors surrounding the proper support of a webfarm - the switches, fail over between switches (don't let the switch be a single point-of-failure!), replication of content, synchronization of server changes, synchronization of application changes, etc, etc.. But a good system administrator (or experienced hosting company) can help address all of these issues for you.

Hopefully this has been a good introduction to webfarms for you, and hopefully I've properly communicated enough of the benefits for you to consider this as a hosting option for yourself. With the rates now down to affordable levels - why not get this additional layer of protection?

Happy hosting!

READ MORE
...