none
Help With Hash / Encryption

    Question

  • I'm newb to hashing and encryption. I created this function to encrypt it and now I'm trying to decrypt it. My Create Hash works but the revert hash is crashing. It wants a string base64[] but it should be a string. What did I do wrong?

    public string CreateHash(string sHash)
            {
                string str = "";
                string[] strArray = new string[16];
                byte[] hash = new MD5CryptoServiceProvider().ComputeHash(Encoding.ASCII.GetBytes(sHash));
                for (int index = 0; index < hash.Length; ++index)
                {
                    strArray[index] = hash[index].ToString("x");
                    str += strArray[index];
                }
                return str;
            }
    
            public string RevertHash(string HashToRevert)
            {
                byte[] inputBuffer = Convert.FromBase64String(HashToRevert);
                byte[] hash = new MD5CryptoServiceProvider().ComputeHash(Encoding.ASCII.GetBytes(HashToRevert));
    
                TripleDESCryptoServiceProvider cryptoServiceProvider = new TripleDESCryptoServiceProvider();
                cryptoServiceProvider.Key = hash;
                cryptoServiceProvider.Mode = CipherMode.ECB;
    
                return Encoding.ASCII.GetString(cryptoServiceProvider.CreateDecryptor().TransformFinalBlock(inputBuffer, 0, inputBuffer.Length));
            }

    Error:

    Invalid length for a Base-64 char array or string."}

    Tuesday, May 2, 2017 4:03 PM

Answers

  • Hi,

     

    According to your codes, you may get a wrong input in your ReverHash method, you input maybe not a string which length is 32. The reason is that if hash[index]<16(like hash[index]=14), hexadecimal is 0e, omit the leading zeros when you convert hash[index] to a string in your CreateHash method. So you can modift your code as follows:

    public static string CreateHash(string sHash)
            {
                string str = "";
                string[] strArray = new string[16];
                byte[] hash = new MD5CryptoServiceProvider().ComputeHash(Encoding.ASCII.GetBytes(sHash));
                for (int index = 0; index < hash.Length; ++index)
                {
                    strArray[index] = hash[index].ToString("x");
                    if (strArray[index].Length < 2) strArray[index] = "0" + strArray[index];
                    //Console.WriteLine(strArray[index].Length);
                    str += strArray[index];
                }
                return str;
            }

    In addition your ReverHash method may have some problems, you can reference to above replies.

    • Marked as answer by old_School Friday, May 12, 2017 3:28 PM
    Wednesday, May 3, 2017 7:21 AM

All replies

  • Cryptographic hash functions like MD5 are deliberately designed to be difficult to reverse. This is called "preimage resistance". If you want a function that you can easily reverse, then consider using an encryption function rather than a hash function.

    (The MD5 function is no longer considered secure but AFAIK researchers still haven't invented a cheap way to find an input that matches a given MD5 hash.)

    Also, byte.ToString("x") makes hexadecimal, which is not the same as Base64.

    Tuesday, May 2, 2017 7:13 PM
  • Hi old_School,

    Thank you for posting here.

    For your question, please add the appsettings in your app.config.

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <startup> 
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
        </startup>
      <appSettings>
        <add key="SecurityKey" value="Syed Moshiur Murshed"/>
      </appSettings>
    </configuration>

    And try the following code.

        static void Main(string[] args)
            {
                string s = Encrypt("hello", true);
                Console.WriteLine(s);
                string str = Decrypt(s, true);
                Console.WriteLine(str);
                Console.ReadKey();
            }
            public static string Encrypt(string toEncrypt, bool useHashing)
            {
                byte[] keyArray;
                byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
    
                System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader();
                // Get the key from config file
                string key = (string)settingsReader.GetValue("SecurityKey", typeof(String));
                //System.Windows.Forms.MessageBox.Show(key);
                if (useHashing)
                {
                    MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
                    keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
                    hashmd5.Clear();
                }
                else
                    keyArray = UTF8Encoding.UTF8.GetBytes(key);
    
                TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
                tdes.Key = keyArray;
                tdes.Mode = CipherMode.ECB;
                tdes.Padding = PaddingMode.PKCS7;
    
                ICryptoTransform cTransform = tdes.CreateEncryptor();
                byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
                tdes.Clear();
                return Convert.ToBase64String(resultArray, 0, resultArray.Length);
            }
            /// <summary>
            /// DeCrypt a string using dual encryption method. Return a DeCrypted clear string
            /// </summary>
            /// <param name="cipherString">encrypted string</param>
            /// <param name="useHashing">Did you use hashing to encrypt this data? pass true is yes</param>
            /// <returns></returns>
            public static string Decrypt(string cipherString, bool useHashing)
            {
                byte[] keyArray;
                byte[] toEncryptArray = Convert.FromBase64String(cipherString);
    
                System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader();
                //Get your key from config file to open the lock!
                string key = (string)settingsReader.GetValue("SecurityKey", typeof(String));
    
                if (useHashing)
                {
                    MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
                    keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
                    hashmd5.Clear();
                }
                else
                    keyArray = UTF8Encoding.UTF8.GetBytes(key);
    
                TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
                tdes.Key = keyArray;
                tdes.Mode = CipherMode.ECB;
                tdes.Padding = PaddingMode.PKCS7;
    
                ICryptoTransform cTransform = tdes.CreateDecryptor();
                byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
    
                tdes.Clear();
                return UTF8Encoding.UTF8.GetString(resultArray);
            }

    

    I hope this would be helpful.

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, May 3, 2017 6:38 AM
    Moderator
  • Hi,

     

    According to your codes, you may get a wrong input in your ReverHash method, you input maybe not a string which length is 32. The reason is that if hash[index]<16(like hash[index]=14), hexadecimal is 0e, omit the leading zeros when you convert hash[index] to a string in your CreateHash method. So you can modift your code as follows:

    public static string CreateHash(string sHash)
            {
                string str = "";
                string[] strArray = new string[16];
                byte[] hash = new MD5CryptoServiceProvider().ComputeHash(Encoding.ASCII.GetBytes(sHash));
                for (int index = 0; index < hash.Length; ++index)
                {
                    strArray[index] = hash[index].ToString("x");
                    if (strArray[index].Length < 2) strArray[index] = "0" + strArray[index];
                    //Console.WriteLine(strArray[index].Length);
                    str += strArray[index];
                }
                return str;
            }

    In addition your ReverHash method may have some problems, you can reference to above replies.

    • Marked as answer by old_School Friday, May 12, 2017 3:28 PM
    Wednesday, May 3, 2017 7:21 AM