<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Sai Panyam.NET &#187; cryptography</title>
	<atom:link href="http://www.saipanyam.net/tag/cryptography/feed" rel="self" type="application/rss+xml" />
	<link>http://www.saipanyam.net</link>
	<description>On all things .NET &#38; Software Engineering</description>
	<lastBuildDate>Thu, 05 Jan 2012 16:42:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>A simple way to encrypt query strings</title>
		<link>http://www.saipanyam.net/2010/03/encrypt-query-strings.html</link>
		<comments>http://www.saipanyam.net/2010/03/encrypt-query-strings.html#comments</comments>
		<pubDate>Fri, 26 Mar 2010 23:12:06 +0000</pubDate>
		<dc:creator>Sai Panyam</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[.NET 3.5]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[cryptography]]></category>
		<category><![CDATA[encryption]]></category>

		<guid isPermaLink="false">http://www.saipanyam.net/?p=190</guid>
		<description><![CDATA[Query strings are used to carry information. We might need to obfuscate them and provide some basic security without writing some elaborate encryption mechanism. Some standard ways of obfuscating, you will find is to Base64Encode the query string(remember to Url encode the resulting string as it is going to be on a url!): string data="query [...]]]></description>
			<content:encoded><![CDATA[<p>Query strings are used to carry information. We might need to obfuscate them and provide some basic security without writing some elaborate encryption mechanism. Some standard ways of obfuscating, you will find is to Base64Encode the query string(remember to Url encode the resulting string as it is going to be on a url!):</p>
<pre>
     string data="query string";
     string encodedData = String.Empty;
       try
       {
           byte[] data_byte = Encoding.UTF8.GetBytes(data);
           encodedData = HttpUtility.UrlEncode(Convert.ToBase64String(data_byte));
        }
        catch (Exception exception)
        {
           //Log exception
        }
        return encodedData;
</pre>
<p>While this works, it provides only <em>obfuscation</em>, but no <em>security</em>. Anyone can do the reverse:</p>
<pre>
        string data="encoded data";
        string decodedData = String.Empty;
        try
        {
             byte[] data_byte = Convert.FromBase64String(HttpUtiltity.UrlDecode(data));
             decodedData = Encoding.UTF8.GetString(data_byte);
        }
        catch (Exception exception)
        {
             //Log exception
         }
         return decodedData;
</pre>
<p>A little more advanced method is to use  <a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.passwordderivebytes.aspx">PasswordDeriveBytes </a> class in .NET to do proper encryption. This has since been replaced with  <a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx">Rfc2898DeriveBytes</a> in .NET 2.0. The reason you would want to use Rfc2898DeriveBytes is because it meets the PKCS #5 standard, which PasswordDerrivedBytes, does not. Both of them are present in<em> System.Security.Cryptography</em> namespace.</p>
<p>What we need to do is:</p>
<ul>
<li>Generate the encryption key and IV(Initialization Vector) from the password and salt.</li>
<li>Create a new instance of the encryptor with the key and IV.</li>
<li>Encrypt the query string.</li>
</ul>
<p>We are not done yet. Improper use of Rfc2898DeriveBytes will result in a performance impact on large sets of data. The cause is the call to GetBytes(int32) method on Rfc2898DeriveBytes class. It uses a pseudo-random number generator based on HMACSHA1. GetBytes initializes a new instance of HMAC is the killer in terms of performance. But the redeeming factor is, subsequent calls to GetBytes does not need to do this initialization.</p>
<p>So we change our implementation to do this expensive call once. Since there is no need to create a new instance of Rfc2898DeriveBytes for each call to encrypt, we will use the same key but change the IV for each message. So remove Rfc2898DeriveBytes from the Encrypt method and pass along the key and IV instead of the password and salt.</p>
<p>Putting all this together here is the final code (fast and efficient):</p>
<pre>
      public static class MyHelper
      {

          #region Private variables and Constants
          private const string ENCRYPTION_KEY = "Wx0Te1rc0pA";
          // Generated from Pass Phrase  "xxxxxxxx12012010" or some pass phrase that you can remember from
          // https://www.bigbiz.com/genkey.html Key Generator Site

          private const string QUERY_PARTS_DELIMITOR = "&amp;";
          private const string QUERY_PARAMS_DELIMITOR = "=";

          ///
          /// The salt value used to strengthen the encryption.
          ///
          private readonly static byte[] SALT = Encoding.ASCII.GetBytes(ENCRYPTION_KEY);
          private readonly static byte[] key;
          private readonly static byte[] iv;
          private static readonly Rfc2898DeriveBytes keyGenerator;

          #endregion

         #region Constructor

         static MyHelper()
         {
            //We create the Rfc2898DerveBytes once as
            //Rfc2898DeriveBytes uses a pseudo-random number generator based on HMACSHA1.
            //When calling GetBytes it initializes a new instance of HMAC which takes some time.
            //Subsequent calls to GetBytes does not need to do this initialization.
            keyGenerator =new Rfc2898DeriveBytes(ENCRYPTION_KEY,SALT);
            key = keyGenerator.GetBytes(32);
            //Generate Initialization Vector - This will be less expensive as we have already intialized Rfc2898DeriveBytes
            iv = keyGenerator.GetBytes(16);
        }

       #endregion

       #region Encrypt/Decrypt Methods

        ///
<summary>
        /// Encrypts any string using the Rijndael algorithm.
        /// </summary>

        ///
<param name="inputText">The string to encrypt.</param>
        ///
<param name="queryStringParam">The name of the query string paramater</param>
        /// <returns>A Base64 encrypted string.</returns>
        public static string Encrypt(string inputText, string queryStringParam)
        {
            //Create a new RijndaelManaged cipher for the symmetric algorithm from the key and iv
            RijndaelManaged rijndaelCipher = new RijndaelManaged {Key = key, IV = iv};

            byte[] plainText = Encoding.Unicode.GetBytes(inputText);

            using (ICryptoTransform encryptor = rijndaelCipher.CreateEncryptor())
            {
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                    {
                        cryptoStream.Write(plainText, 0, plainText.Length);
                        cryptoStream.FlushFinalBlock();
                        return "?" + queryStringParam + "=" + Convert.ToBase64String(memoryStream.ToArray());
                    }
                }
            }
        }

        ///
<summary>
        /// Decrypts a previously encrypted string.
        /// </summary>

        ///
<param name="inputText">The encrypted string to decrypt.</param>
        /// <returns>A decrypted string.</returns>
        public static string Decrypt(string inputText)
        {
            RijndaelManaged rijndaelCipher = new RijndaelManaged();
            byte[] encryptedData = Convert.FromBase64String(inputText);

            using (ICryptoTransform decryptor = rijndaelCipher.CreateDecryptor(key, iv))
            {
                using (MemoryStream memoryStream = new MemoryStream(encryptedData))
                {
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
                    {
                        byte[] plainText = new byte[encryptedData.Length];
                        int decryptedCount = cryptoStream.Read(plainText, 0, plainText.Length);
                        return Encoding.Unicode.GetString(plainText, 0, decryptedCount);
                    }
                }
            }
        }

        #endregion

       }
</pre>
<p>The only draw back is this doesn&#8217;t give you full security.  This method will provide basic security in terms of stopping the hacker from deterministically manipulating the encrypted string. So it is a more a deterrence than a verification strategy. We can tell if someone tampers with the encrypted string only if the decryption &#8216;fails&#8217; to decrypt to something you recognize or expect.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saipanyam.net/2010/03/encrypt-query-strings.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

