【问题标题】:Bad data while decrypting information using Triple DES使用三重 DES 解密信息时出现错误数据
【发布时间】:2012-05-28 07:40:04
【问题描述】:

我正在通过 .Net 开发一个 mvc 应用程序,以保护我的敏感信息,例如 web.config 中的信息我有两个使用三重 DES 加密和解密信息的函数,但是我是新手,并且在朋友的帮助下成功到达。

加密功能工作正常并返回正确的字符串但是当我尝试解密我得到的相同字符串时

Exception Details: System.Security.Cryptography.CryptographicException: Bad Data.

Decrypt 函数的这一行出错:

Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length);

我尝试通过我已包含在注释代码中的几种方式来解决它,但它们没有帮助,请帮我解决这个问题。

public static string Encrypt(string Message, string Passphrase)
    {
        byte[] Results;
        System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
        MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
        byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(GetSHA256String(Passphrase)));
        TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
        TDESAlgorithm.Key = TDESKey;
        TDESAlgorithm.Mode = CipherMode.ECB;
        TDESAlgorithm.Padding = PaddingMode.PKCS7;
        byte[] DataToEncrypt = UTF8.GetBytes(Message);
        try
        {
            ICryptoTransform Encryptor = TDESAlgorithm.CreateEncryptor();
            Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length);
        }
        finally
        {
            TDESAlgorithm.Clear();
            HashProvider.Clear();
        }
        return Convert.ToBase64String(Results);
        //return Encoding.UTF8.GetString(Results);

    }

    public static string Decrypt(string Message, string Passphrase)
    {
        byte[] Results;
        System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
        MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
        byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(GetSHA256String(Passphrase)));
        TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
        TDESAlgorithm.Key = TDESKey;
        TDESAlgorithm.Mode = CipherMode.ECB;
        TDESAlgorithm.Padding = PaddingMode.PKCS7;
        try
        {
            byte[] DataToDecrypt = Convert.FromBase64String(Message);
            //byte[] DataToDecrypt = UTF8.GetBytes(Message);
            //byte[] DataToDecrypt = Encoding.UTF8.GetBytes(Message);
            ICryptoTransform Decryptor = TDESAlgorithm.CreateDecryptor();
            Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length); // << ERROR is here.
        }
        finally
        {
            TDESAlgorithm.Clear();
            HashProvider.Clear();
        }
        return UTF8.GetString(Results);
    }

【问题讨论】:

  • 还要检查 PaddingMode 参数,特别是 PaddingMode.Zeros 会使最终结果与额外的 \0 不同

标签: .net encryption cryptography 3des tripledes


【解决方案1】:

TripleDES 算法指定了一个 IV(初始化向量),用于确保使用相同密钥对相同数据进行重复加密会产生不同的密文。要成功解密,解密过程中必须使用与加密期间相同的 IV。

由于您当前未在执行加密时指定 IV (TDESAlgorithm.IV),因此算法将其设置为随机值。该算法还将解密期间使用的 IV 设置为随机值(但与加密中使用的不同),因此解密过程失败。

要纠正该问题,您可以使用以下方法(请注意,在加密阶段随机生成的 IV 是从 Encrypt 方法输出并传递给 Decrypt 方法):

public static string Encrypt(string Message, string Passphrase, out byte[] iv)
{
    byte[] Results;
    System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
    MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
    byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(GetSHA256String(Passphrase)));
    TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
    TDESAlgorithm.Key = TDESKey;
    TDESAlgorithm.Mode = CipherMode.ECB;
    TDESAlgorithm.Padding = PaddingMode.PKCS7;
    // Capture the randomly generated IV
    iv = TDESAlgorithm.IV;
    byte[] DataToEncrypt = UTF8.GetBytes(Message);
    try
    {
        ICryptoTransform Encryptor = TDESAlgorithm.CreateEncryptor();
        Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length);
    }
    finally
    {
        TDESAlgorithm.Clear();
        HashProvider.Clear();
    }
    return Convert.ToBase64String(Results);
    //return Encoding.UTF8.GetString(Results);
}

public static string Decrypt(string Message, string Passphrase, byte[] iv)
{
    byte[] Results;
    System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
    MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
    byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(GetSHA256String(Passphrase)));
    TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
    TDESAlgorithm.Key = TDESKey;
    // Apply the same IV used during encryption
    TDESAlgorithm.IV = iv;
    TDESAlgorithm.Mode = CipherMode.ECB;
    TDESAlgorithm.Padding = PaddingMode.PKCS7;
    try
    {
        byte[] DataToDecrypt = Convert.FromBase64String(Message);
        //byte[] DataToDecrypt = UTF8.GetBytes(Message);
        //byte[] DataToDecrypt = Encoding.UTF8.GetBytes(Message);
        ICryptoTransform Decryptor = TDESAlgorithm.CreateDecryptor();
        Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length); // << ERROR is here.
    }
    finally
    {
        TDESAlgorithm.Clear();
        HashProvider.Clear();
    }
    return UTF8.GetString(Results);
}

请注意,如果您以后要成功解密数据,则需要将 IV 与密文一起存储。

【讨论】:

  • 常见的做法是在传输前将IV加在实际密文的前面,这样接收端就得到一份副本。解密时,只需先读取IV,然后用它来解密输入流的其余部分。
  • @Iridium & @rossum:谢谢你这么清楚的回答先生,就像你说的我应该在加密字符串的末尾添加iv,所以你能告诉我吗我如何连接两个 byte[] 变量我正在尝试这个Results = Results + iv; 但它当然不起作用?
  • IV 应该在加密字节的 开始 处,因为您的接收者需要它来开始加密。要在 C# 中连接数组,请参阅 stackoverflow.com/questions/415291/…
【解决方案2】:

我最近遇到了这个问题。一个空值已传递给Decrypt()。如果Message (要解密的数据) 为空,TransformFinalBlock()(在 Decrypt() 内)会抛出 Bad Data 异常。

因此,请在调用 Decrypt() 之前对要解密的数据添加一个空/空检查。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多