Posts

SHA1 and MD5 hashing algorithms

When storing passwords in database, it is considered a good practice to hash them first. The most common way to do that is to use MD5 or SHA hashing algorithms. Hashing passwords is more secure because after creating a hash from the user’s password theoretically there is not way to get the password back from it. In reality MD5 is more vulnerable to “collision attacks” as it uses 128 bit value while SHA1 uses 160 bits which makes it harder to crack.

The disadvantage of hashing passwords is the fact that if an users forgets his password, we cannot send him a reminder. We will have to reset it first.

Theoretically if someone will steal our database, it is possible to use bruit force attack to find the original passwords by trying different combinations of words and numbers. To prevent that we can add our custom string to the user’s string before hashing. This makes it more difficult to crack the passwords having only database without our application files where the custom string is being stored.

 class Program
    {
        static void Main(string[] args)
        {
            string md5 = CreateMD5Hash("test");
            //result: CY9rzUYh03PK3k6DJie09g==

            string sha1 = CreateSHA1Hash("test");
            //result: qUqP5cyxm6YcTAhz05Hph5gvu9M
        }

        /// <summary>
        /// Creates MD5 hash of text
        /// </summary>
        public static string CreateMD5Hash(string clearText)
        {
            return Convert.ToBase64String(MD5.Create().ComputeHash(UnicodeEncoding.UTF8.GetBytes(clearText)));
        }

        /// <summary>
        /// Creates SHA1 hash of text
        /// </summary>
        public static string CreateSHA1Hash(string clearText)
        {
            return Convert.ToBase64String(SHA1.Create().ComputeHash(UnicodeEncoding.UTF8.GetBytes(clearText))).TrimEnd('=');
        }
    }

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...Loading...

Encrypting Url parameters with DES

When reading and validating URL parameters you probably came across the situation that you wanted to hide some values for security reasons. Such a situations happen very often eg. when confirming email address of an user by sending validation link or by validating payment callback etc.

One of the solutions is to encrypt Url parameters using DES algorithm. DES it’s a symmetric algorithm that allows you to encrypt and decrypt values using shared public key. It is advisable to change public key from time to time for security reasons.

Below are two helper methods needed to encrypt and decrypt values:

    /// <summary>
    /// Encrypts an string using provided public key (DES)
    /// </summary>
    /// <param name="stringToEncrypt">String to be encrypted</param>
    /// <param name="sEncryptionKey">Public key</param>
    /// <returns>string</returns>
    public static string DES_encrypt(string stringToEncrypt, string sEncryptionKey)
    {
     if (stringToEncrypt.Length <= 3) { throw new Exception("Invalid input string"); }

     byte[] key = { };
     byte[] IV = { 10, 20, 30, 40, 50, 60, 70, 80 }; //defining vectors
     byte[] inputByteArray;
     key = Encoding.UTF8.GetBytes(sEncryptionKey.Substring(0, 8));
     using (var des = new DESCryptoServiceProvider())
     {
        inputByteArray = Encoding.UTF8.GetBytes(stringToEncrypt);
        using (var ms = new MemoryStream())
        {
            using (var cs = new CryptoStream(ms, des.CreateEncryptor(key, IV), CryptoStreamMode.Write))
            {
                cs.Write(inputByteArray, 0, inputByteArray.Length);
                cs.FlushFinalBlock();
                return Convert.ToBase64String(ms.ToArray());
            }
        }
      }
   }

and

    /// <summary>
    /// Decrypts an string using provided public key (DES)
    /// </summary>
    /// <param name="stringToDecrypt">String to be decrypted</param>
    /// <param name="sEncryptionKey">Public key</param>
    /// <returns>string</returns>
    public static string DES_decrypt(string stringToDecrypt, string sEncryptionKey)
    {
     if (stringToDecrypt.Length <= 3) { throw new Exception("Invalid input string"); }

     byte[] key = { };
     byte[] IV = { 10, 20, 30, 40, 50, 60, 70, 80 };//defining vectors
     byte[] inputByteArray = new byte[stringToDecrypt.Length];
     key = Encoding.UTF8.GetBytes(sEncryptionKey.Substring(0, 8));
     using (var des = new DESCryptoServiceProvider())
     {
        inputByteArray = Convert.FromBase64String(stringToDecrypt.Replace(" ", "+"));
        using (var ms = new MemoryStream())
        {
            using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(key, IV), CryptoStreamMode.Write))
            {
                cs.Write(inputByteArray, 0, inputByteArray.Length);
                cs.FlushFinalBlock();
                var encoding = Encoding.UTF8;
                return encoding.GetString(ms.ToArray());
            }
        }
     }
   }

In real life scenario when sending validation email we are simply encrypting our parametrized string the way shown bellow:

  var urlParam = txtEmail.Text + ";" + userID + ";" + DateTime.Now.ToString();

  var encryptedParam = Encryption.DES_encrypt(urlParam, "12345678");

  //send confirmation email with link: https://www.myadress.com/validate.aspx?sid=encryptedParam

When someone clicks the link and comes to our page we need to decrypt values and read the data.

   var encryptedParam = Request["sid"];

   var decryptedParam = Encryption.DES_decrypt(encryptedParam, "12345678");

   var email = decryptedParam.Split(';')[0];
   var userID = decryptedParam.Split(';')[1];
   var dateSent = DateTime.Parse(decryptedParam.Split(';')[2]);

As you probably have noticed, we use same public key to encrypt and decrypt values. In our situation the public key is safe because it is only stored on our server and is not being sent across the network.

For the above functions to be fully functional you need implement basic validation. It is also a good practice to add timestamp date to encrypted string so we can ensure the data was sent within defined time frame, lets say within last 5 minutes. After that the data will expire and wont be accepted by our application.

DES it’s quite save and efficient algorithm that you can use in your daily programming. It should be suitable in most case scenarios, unless you are building banking system 🙂

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...Loading...