C# 三重 DES 包装器问题:TransformFinalBlock 抛出"错误数据"



我在C#中有一个三重DES包装器,它由两个静态函数EncryptDecrypt组成。偶尔,Decrypt会失败,TransformFinalBlock(..., ...)会抛出错误"Bad data"。

  • 为什么会发生这种情况
  • 解决方案是什么

提前谢谢。

public static string Encrypt(string toencrypt, string key, bool usehashing = true)
{
    byte[] keyArray;
    byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toencrypt);
    byte[] resultArray;
    //If hashing use get hashcode regards to your key
    if (usehashing)
    {
        MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
        keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
        //Always release the resources and flush data
        // of the Cryptographic service provide. Best Practice
        hashmd5.Clear();
    }
    else
        keyArray = UTF8Encoding.UTF8.GetBytes(key);
    TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
    //set the secret key for the tripleDES algorithm
    tdes.Key = keyArray;
    //mode of operation. there are other 4 modes.
    //We choose ECB(Electronic code Book)
    tdes.Mode = CipherMode.ECB;
    //padding mode(if any extra byte added)
    tdes.Padding = PaddingMode.PKCS7;
    ICryptoTransform cTransform = tdes.CreateEncryptor();
    try
    {
        //transform the specified region of bytes array to resultArray
        resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
    }
    catch (System.Exception ex)
    {
        //Release resources held by TripleDes Encryptor
        tdes.Clear();
        return "";
    }
    //Release resources held by TripleDes Encryptor
    tdes.Clear();
    //Return the encrypted data into unreadable string format
    return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
public static string Decrypt(string todecrypt, string key, bool usehashing = true)
{
    byte[] keyArray;
    byte[] toEncryptArray;
    byte[] resultArray;
    //get the byte code of the string
    try
    {
        toEncryptArray = Convert.FromBase64String(todecrypt.Replace(" ", "+"));//The replace happens only when spaces exist in the string (hence not a Base64 string in the first place).
    }
    catch (System.Exception ex)
    {
        return "";
    }
    if (usehashing)
    {
        //if hashing was used get the hash code with regards to your key
        MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
        keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
        //release any resource held by the MD5CryptoServiceProvider
        hashmd5.Clear();
    }
    else
    {
        //if hashing was not implemented get the byte code of the key
        keyArray = UTF8Encoding.UTF8.GetBytes(key);
    }
    TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
    //set the secret key for the tripleDES algorithm
    tdes.Key = keyArray;
    //mode of operation. there are other 4 modes. 
    //We choose ECB(Electronic code Book)
    tdes.Mode = CipherMode.ECB;
    //padding mode(if any extra byte added)
    tdes.Padding = PaddingMode.PKCS7;
    ICryptoTransform cTransform = tdes.CreateDecryptor();
    try
    {
        resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
    }
    catch (System.Exception ex)
    {
        //Release resources held by TripleDes Encryptor                
        tdes.Clear();
        return "";
    }
    //Release resources held by TripleDes Encryptor                
    tdes.Clear();
    //return the Clear decrypted TEXT
    return UTF8Encoding.UTF8.GetString(resultArray);
}

一个一旦加密就会导致Decrypt失败的示例字符串是:

AgAAAA*AQAAAA*aAAAAA*jfgGTw*nY+sHZ2PrBmdj6wVnY+sEZ2PrA2dj6wFk4GhCJOHoQqdj6x9nY+seQ**.AAMAAA**+L7PHiJ76M8OTV4BjXCkuDgDG2u7AcW87p1KU7KTSCKI3YTnYAcGk1gyS62AvZO4g1FrsVbzoAnsX9Y0Ju+V9YjaYr9+Xr+pen4Sis0NjRvntv0gqU0QZOj9jKXx1Izc9Dw1HCUqjUGBcwakQo6kBlvb2v2/pV9dM4B3RM6m7rmaW79CSc7CC3DQjnqA5HMHC5k65pOK0KT76MzTawYQotNo0AbTO3HpVc8NNjSsIP7vtxXBmbc6TfXahw1zLTvC4iTSPnsgz0jhxvHhHD+N0cblfQhAK/nt2IZQuWGL3jW0oPpPJnjGMWQPDLXbNwp23WUv8GXIPKevXbushYKjutmdqJT7C1mcB45XhbYCVUVbLIja1AV831YeHqqke2msSaisg37UM+urL9EFIueUHZgZryhQUSjAhZDiHXqosoQou92RqbTK5YTqYY+zyBBzRt2r7KS3v5u9smtWMNk8Xcn42a6pFFxd6g4u0/s/SVm7NFb2UbREvp 75lBVxEQv5IIznPSHfDnLtuX8pLfrZ/AVQ+gM9AGvzBjHGNYDQJ6VhgkHOZMeuLISJXjfGX0ZPFYKd+COPbLukOSlIB5epRDnuggTLnthpN06Kle+iDqz1Q96ty4mfzwuhRwxvQ7EMzTykHXxC9bLKMr86K/vart2D9w1g9RtyS+pekgW8lkutWWGdu1eZml/5abNmlW5VgSJiuA9Yyrd2UNjUl6/a0oMKHPk6b2gZkpmENpO7auC9HA2gO

然而,大多数字符串不会导致它失败。我猜这一定和一些特殊的角色有关。

首先,请提供初始未加密密钥和字符串,该密钥和字符串会生成失败的加密块。然后我们可能有更好的机会弄清楚为什么会出现问题。然而,根据要求,我在您的代码中看到了一些潜在的陷阱,主要与不处理实现IDisposable的类型有关。这里有一个代码的小重构,它考虑到了这一点(以及其他一些小调整):

    public static string Encrypt(string toencrypt, string key, bool usehashing = true)
    {
        byte[] keyArray;
        // If hashing use get hash code regards to your key
        if (usehashing)
        {
            using (var hashmd5 = new MD5CryptoServiceProvider())
            {
                keyArray = hashmd5.ComputeHash(Encoding.UTF8.GetBytes(key));
            }
        }
        else
        {
            keyArray = Encoding.UTF8.GetBytes(key);
        }
        // set the secret key for the tripleDES algorithm
        // mode of operation. there are other 4 modes.
        // We choose ECB(Electronic code Book)
        // padding mode(if any extra byte added)
        using (var tdes = new TripleDESCryptoServiceProvider
        {
            Key = keyArray,
            Mode = CipherMode.ECB,
            Padding = PaddingMode.PKCS7
        })
        using (var transform = tdes.CreateEncryptor())
        {
            try
            {
                var toEncryptArray = Encoding.UTF8.GetBytes(toencrypt);
                // transform the specified region of bytes array to resultArray
                var resultArray = transform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
                // Return the encrypted data into unreadable string format
                return Convert.ToBase64String(resultArray, 0, resultArray.Length);
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }
    }
    public static string Decrypt(string todecrypt, string key, bool usehashing = true)
    {
        byte[] toEncryptArray;
        // get the byte code of the string
        try
        {
            toEncryptArray = Convert.FromBase64String(todecrypt.Replace(" ", "+")); // The replace happens only when spaces exist in the string (hence not a Base64 string in the first place).
        }
        catch (Exception)
        {
            return string.Empty;
        }
        byte[] keyArray;
        if (usehashing)
        {
            // if hashing was used get the hash code with regards to your key
            using (var hashmd5 = new MD5CryptoServiceProvider())
            {
                keyArray = hashmd5.ComputeHash(Encoding.UTF8.GetBytes(key));
            }
        }
        else
        {
            // if hashing was not implemented get the byte code of the key
            keyArray = Encoding.UTF8.GetBytes(key);
        }
        // set the secret key for the tripleDES algorithm
        // mode of operation. there are other 4 modes. 
        // We choose ECB(Electronic code Book)
        // padding mode(if any extra byte added)
        using (var tdes = new TripleDESCryptoServiceProvider
        {
            Key = keyArray,
            Mode = CipherMode.ECB,
            Padding = PaddingMode.PKCS7
        })
        using (var transform = tdes.CreateDecryptor())
        {
            try
            {
                var resultArray = transform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
                // return the Clear decrypted TEXT
                return Encoding.UTF8.GetString(resultArray);
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }
    }

相关内容

  • 没有找到相关文章

最新更新