C# Code Snippets

Extension Methods for
String hasing and Encryption

Stefan Prodan

Since MD5 and SHA1 are not consider secure any more, the hashing is done using SHA256 with a random salt. The salt can be hardcoded into your code or stored in a database. You can call the method with ref null as salt and the code will generate a random one using RNGCryptoServiceProvider. The string encryption / decryption methods uses Rijndael algorithm. Rijndael has been approved by NSA to be used for classified information protection.

Platform: .NET Framework 3.5

public static class ExtensionMethods2
{
    /// <summary>
    /// Suitable for password hashing
    /// </summary>
    /// <param name="salt">A random salt will be generated if input is null</param>
    /// <returns>Lenght 64</returns>
    public static string ComputeHash(this string str, ref string salt)
    {
        //if you don't care about the hash being reverted
        //SHA1Managed is faster with a smaller output
        var hasher = new SHA256Managed();
        int keyLength = 4;

        byte[] data = Encoding.UTF8.GetBytes(str);
        byte[] key = new byte[keyLength];
        byte[] dataReady = new byte[data.Length + keyLength];

        if (salt == null)
        {
            //random salt
            using (var random = new RNGCryptoServiceProvider())
            {
                random.GetNonZeroBytes(key);
            }

            salt = Convert.ToBase64String(key);
        }

        //memory consuming operation
        Array.Copy(Encoding.UTF8.GetBytes(salt), key, keyLength);
        Array.Copy(data, dataReady, data.Length);
        Array.Copy(key, 0, dataReady, data.Length, keyLength);

        //hash
        return BitConverter.ToString(hasher.ComputeHash(dataReady)).Replace("-", string.Empty);
    }

    /// <summary>
    /// Encrypt using Rijndael
    /// </summary>
    public static string Encrypt(this string str, string password)
    {
        byte[] salt = Encoding.UTF8.GetBytes(password.Length.ToString());
        byte[] text = Encoding.UTF8.GetBytes(str);
        byte[] cipher;

        var key = new PasswordDeriveBytes(password, salt);

        using (ICryptoTransform encryptor = new RijndaelManaged().CreateEncryptor(key.GetBytes(32), key.GetBytes(16)))
        using (MemoryStream memoryStream = new MemoryStream())
        using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
        {
            cryptoStream.Write(text, 0, text.Length);
            cryptoStream.FlushFinalBlock();
            cipher = memoryStream.ToArray();
        }
        return Convert.ToBase64String(cipher);
    }

    /// <summary>
    /// Decrypt Rijndael encrypted string
    /// </summary>
    public static string Decrypt(this string str, string password)
    {
        byte[] salt = Encoding.UTF8.GetBytes(password.Length.ToString());
        byte[] text = Convert.FromBase64String(str);
        var key = new PasswordDeriveBytes(password, salt);
        int outLen;

        using (ICryptoTransform decryptor = new RijndaelManaged().CreateDecryptor(key.GetBytes(32), key.GetBytes(16)))
        using (MemoryStream memoryStream = new MemoryStream(text))
        using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
        {
            text = new byte[text.Length];
            outLen = cryptoStream.Read(text, 0, text.Length);
        }
        return Encoding.UTF8.GetString(text, 0, outLen);
    }
}

http://www.stefanprodan.eu/2011/02/c-extensions-collection-no-2/

 

Back to C# Code Snippet List