【问题标题】:Encrypt and Decrypt password加密和解密密码
【发布时间】:2012-10-03 02:18:42
【问题描述】:

我正在使用以下代码来加密和解密 asp.net 中的密码。加密工作完美,但解密时抛出此错误 Invalid length for a Base-64 char array.

我的密码是 123,我使用它来加密:HttpUtility.UrlEncode(CryptorEngine.Encrypt(strpassword, true)); 并解密我使用它如下:

CryptorEngine.Decrypt(HttpUtility.UrlDecode(strpassword), true));

这是代码:

 public class CryptorEngine
    {
        /// <summary>
        /// Encrypt a string using dual encryption method. Return a encrypted cipher Text
        /// </summary>
        /// <param name="toEncrypt">string to be encrypted</param>
        /// <param name="useHashing">use hashing? send to for extra secirity</param>
        /// <returns></returns>
        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);
        }
    }

【问题讨论】:

  • 您是否考虑过不解密密码,而是检查哈希是否匹配,而不是解密密码以检查输入是否与加密密码匹配?正如索尼发现的那样,如果加密的密码是可解密的,我认为它不安全。只是一个建议。
  • 我假设您已经调试并检查了进出各种函数的值?加密为您提供的 Base64 编码字符串与您传递给解密函数的字符串相比如何? base64 字符串的长度应该是四个字符的倍数...
  • 我的 123 加密密码是 VCZaNZapEXY%3d 但在登录时看不到它,当提供 123 作为密码时,它在这一行失败 yte[] toEncryptArray = Convert.FromBase64String(cipherString);的Decrpt方法
  • @Sam1:如果你打破那条线,cipherString 的值是多少?
  • 你能告诉我你的加密和解密输入是什么吗?

标签: c# asp.net passwords encryption


【解决方案1】:

在 URL 中有与加密输出冲突的字符,至少在我的代码中,这就是问题所在。所以我用这两个函数来改变这个字符并避免这种情况。

public static string ChangeSPChart(string sTheInput)
{
    StringBuilder sRetMe = new StringBuilder(sTheInput);

    sRetMe.Replace('+', '-');
    sRetMe.Replace('/', '*');
    sRetMe.Replace('=', '!');

    return sRetMe.ToString();
}

public static string FixSPChart(string sTheInput)
{
    StringBuilder sRetMe = new StringBuilder(sTheInput);

    sRetMe.Replace('-', '+');
    sRetMe.Replace('*', '/');
    sRetMe.Replace('!', '=');

    return sRetMe.ToString();
}

加密/解密代码为:

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();
    var encrypted = Convert.ToBase64String(resultArray, 0, resultArray.Length);

    // here I change it
    return  ChangeSPChart(encrypted);
}
/// <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)
{
    cipherString = FixSPChart(cipherString);

    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);
}

【讨论】:

  • @Sam1 使用它,调试它以定位并查看字符串是否中断。
  • 我是否需要用 HttpUtility.UrlDecode 和 HttpUtility.UrlEncode 包围我的密码
  • 我觉得这不应该是必要的。如果你 urlencode +/= 那么它会给你%2b%2f%3d 这不需要任何魔法替换所以我不确定这实际上是问题......
  • @Chris 你可能是对的,我不记得我为什么要那样做 - 对我来说很简单,此时我正在处理一个程序,我太累了,我记不得了只需编写此解决方案以提供帮助。
  • @Sam1:如果答案实际上不包含解决方案,那么您不应将其标记为已接受的答案。我承认我这样说的部分原因是我的回答确实包含您的密码需要在被传递到解密函数之前加密的建议。
【解决方案2】:

hiii 请使用此代码,这很好用

//信用卡的加密方式

public string EncryptTripleDES(string Plaintext, string Key)
{

    System.Security.Cryptography.TripleDESCryptoServiceProvider DES =

    new System.Security.Cryptography.TripleDESCryptoServiceProvider();

    System.Security.Cryptography.MD5CryptoServiceProvider hashMD5 =

    new System.Security.Cryptography.MD5CryptoServiceProvider();

    DES.Key = hashMD5.ComputeHash(System.Text.ASCIIEncoding.ASCII.GetBytes(Key));

    DES.Mode = System.Security.Cryptography.CipherMode.ECB;

    System.Security.Cryptography.ICryptoTransform DESEncrypt = DES.CreateEncryptor();

    Buffer = System.Text.ASCIIEncoding.ASCII.GetBytes(Plaintext);
   string TripleDES = Convert.ToBase64String(DESEncrypt.TransformFinalBlock(Buffer, 0, Buffer.Length));

    return TripleDES;

}
//Decryption Method 

public string DecryptTripleDES(string base64Text, string Key)
{

    System.Security.Cryptography.TripleDESCryptoServiceProvider DES =

    new System.Security.Cryptography.TripleDESCryptoServiceProvider();

    System.Security.Cryptography.MD5CryptoServiceProvider hashMD5 =

    new System.Security.Cryptography.MD5CryptoServiceProvider();
    DES.Key = hashMD5.ComputeHash(System.Text.ASCIIEncoding.ASCII.GetBytes(Key));
    DES.Mode = System.Security.Cryptography.CipherMode.ECB;
    System.Security.Cryptography.ICryptoTransform DESDecrypt = DES.CreateDecryptor();
    Buffer = Convert.FromBase64String(base64Text);

    string DecTripleDES = System.Text.ASCIIEncoding.ASCII.GetString(DESDecrypt.TransformFinalBlock(Buffer, 0, Buffer.Length));
   return DecTripleDES;

}

【讨论】:

    【解决方案3】:

    您提供的代码可以正常工作。我用这个小程序对其进行了测试:

    void Main()
    {
        var cryptB64 =CryptorEngine.Encrypt("123", true);
        var encoded = HttpUtility.UrlEncode(cryptB64);
        var decoded = HttpUtility.UrlDecode(encoded);
        var decrypted = CryptorEngine.Decrypt(decoded, true);
    
        bool matches = (decrypted=="123");
        Console.WriteLine(matches);
    }
    

    它按预期返回 true。

    问题可能是您在某些时候破坏了您的加密值。我猜它是通过 HTTP 传输的,我猜这就是问题所在。

    补充说明:

    当调用CryptorEngine.Decrypt(HttpUtility.UrlDecode(strpassword), true)); 时,您需要确保strpassword 是密码的加密 形式,而不是您要比较的明文密码。

    【讨论】:

    • 当你把它放在 url 上,然后从 url 中获取结果,如果它包含像+ 这样的符号,'=` 是中断。您的测试是有效的,因为您实际上并没有将它放在 url 上。
    • @Aristos:是的。完全正确。我的观点是,问题中的代码与问题无关,而且他找错了地方。您的回答解决了传输问题,我正在解决问题中的错误假设,并试图鼓励他学习如何自己调试此类问题(通过检查方法的进出)。 (给你+1,因为我认为你的技术可能是解决方案的关键)。
    • @Aristos:我实际上收回了关于您解决问题的答案。 urlencoding 应该已经解决了您所说的传输问题。
    【解决方案4】:

    这里有点晚了,但问题可能是别的(对我来说)。

    Request.Querystring 已经进行了一些解码。就我而言,我基本上是解码了两次。添加第二个“HttpUtility.UrlEncode”就可以了(至少在 20 次不同的测试之后)。

    我还没有从微软那里找到关于这种行为的确切文档,旧书被存放起来(我尽量不离开我的椅子),但这些链接很有帮助:

    does Request.Querystring automatically url decode a string?

    http://forums.asp.net/t/1354726.aspx?Request+Querystring+without+decoding+possible+

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-09
      • 2017-04-01
      • 2016-12-08
      • 2019-05-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多