在C#中使用3DES加密的ColdFusion中解密字符串

时间:2012-02-08 15:22:59

标签: c# asp.net coldfusion 3des

我们无法解密之前使用3DES和C#加密的ColdFusion中的字符串。以下是我们最初用于加密字符串的代码:

    public static string EncryptTripleDES(string plaintext, string key)
    {
    TripleDESCryptoServiceProvider DES = new TripleDESCryptoServiceProvider();
    MD5CryptoServiceProvider hashMD5 = new MD5CryptoServiceProvider();
    DES.Key = hashMD5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(key));
    DES.Mode = CipherMode.ECB;
    ICryptoTransform DESEncrypt = DES.CreateEncryptor();
    byte[] Buffer = ASCIIEncoding.ASCII.GetBytes(plaintext);

    string EncString = Convert.ToBase64String(DESEncrypt.TransformFinalBlock(Buffer, 0, Buffer.Length));
    EncString = EncString.Replace("+", "@@12");

    return EncString;
    }

我们尝试过使用这里的建议:

TripleDES Encryption - .NET and ColdFusion not playing nice

..没有运气。这是我们的CF代码和错误:

  <cfset variables.theKey = "blahblah" />
  <cfset variables.theAlgorithm = "DESede/CBC/PKCS5Padding">
  <cfset variables.theEncoding = "Base64">
  <cfset strTest = decrypt(#DB.PASSWORD#, variables.theKey, variables.theAlgorithm, variables.theEncoding)>

返回错误:尝试加密或解密输入字符串时发生错误:''无法解码字符串“blahblah”

因此,看起来它正在尝试解密密钥而不是字符串,但这不是ColdFusion中概述解密函数的方式。有什么想法吗?

更新:尝试使用以下CF代码,但返回的错误仍然是“尝试加密或解密输入字符串时发生错误:给定最终块未正确填充。”

<cfset dbPassword  = "Hx41SYUrmnFPa31QCH1ArCHN1YOF8IAL">
<cfset finalText   = replace(dbPassword, "@@12", "+", "all")>
<cfset theKey      = "abcdefgh">
<cfset theKeyInBase64 = toBase64(theKey)>
<cfset hashedKey   = hash( theKeyInBase64, "md5" )>
<cfset padBytes    = left( hashedKey, 16 )>
<cfset keyBytes    = binaryDecode( hashedKey & padBytes , "hex" )>
<cfset finalKey    = binaryEncode( keyBytes, "base64" )>
<cfset decrypted = decrypt( finalText, finalKey, "DESede/ECB/PKCS5Padding", "base64" )>
Decrypted String: <cfdump var="#decrypted#">

更新

如果您遵循评论,解决方案就是改变:

<cfset hashedKey   = hash( theKeyInBase64, "md5" )>

要:

<cfset hashedKey   = hash( theKey, "md5" )>

最终的代码是:

<cfset dbPassword  = "Hx41SYUrmnFPa31QCH1ArCHN1YOF8IAL">
<cfset finalText   = replace(dbPassword, "@@12", "+", "all")>
<cfset theKey      = "abcdefgh">
<cfset hashedKey   = hash( theKey, "md5" )>
<cfset padBytes    = left( hashedKey, 16 )>
<cfset keyBytes    = binaryDecode( hashedKey & padBytes , "hex" )>
<cfset finalKey    = binaryEncode( keyBytes, "base64" )>
<cfset decrypted = decrypt( finalText, finalKey, "DESede/ECB/PKCS5Padding", "base64" )>
Decrypted String: <cfdump var="#decrypted#">

1 个答案:

答案 0 :(得分:5)

在您的c#函数中看起来有一些额外的扭曲,您需要处理以实现兼容性:

  1. .NET函数修改加密的字符串。你需要 反转这些更改,因此解密会将其识别为有效的base64:

    <!--- reverse replacements in encrypted text ie #DB.Password# --->
    <cfset dbPassword = "uAugP@@12aP4GGBOLCLRqxlNPL1PSHfTNEZ">
    <cfset finalText = replace(dbPassword, "@@12", "+", "all")>
    
  2. 该函数还使用创建16字节密钥的哈希。对于该算法,CF / java需要24 byte key。因此,您必须首先对密钥进行哈希并pad it to the proper length。否则,decrypt()会抱怨密钥太小。

    注意:CF还希望最终密钥是base64编码的。错误无法解码字符串“blahblah”表示您的输入密钥不在base64中。

    <!--- hash and pad the key (ie "blahblah"), then convert to base64 for CF --->
    <cfset theKeyInBase64 = "rpaSPvIvVLlrcmtzPU9/c67Gkj7yL1S5">
    <cfset hashedKey   = hash( theKeyInBase64, "md5" )>
    <cfset padBytes    = left( hashedKey, 16 )>
    <cfset keyBytes    = binaryDecode( hashedKey & padBytes , "hex" )>
    <cfset finalKey    = binaryEncode( keyBytes, "base64" )>
    
  3. 最后,反馈模式必须匹配。由于.NET代码使用安全性较低的ECB模式,因此CF代码也必须使用该模式。

    <!--- .net code uses the less secure ECB mode --->
    <cfset decrypted = decrypt( finalText, finalKey, "DESede/ECB/PKCS5Padding", "base64" )>
    Decrypted String: <cfdump var="#decrypted#">
    
  4. 需要注意的另一个问题是编码。在CF中,加密/解密始终将输入字符串解释为UTF8,而.NET函数使用ASCII。为了完全兼容,双方应使用相同的编码,在本例中为UTF8。


  5. 更新:

    我用任意8个字符的键(而不是base64字符串)测试了上面的内容,CF9仍然正确地解密了字符串。

    // .NET Code
    String text = "some text to encrypt";
    String key = "abcdefgh";
    String encrypted = EncryptTripleDES(text, key);
    // result: encrypted=Hx41SYUrmnFPa31QCH1ArCHN1YOF8IAL
    Console.WriteLine("encrypted={0}", encrypted);
    
    <!--- same code, only the encrypted text and key changed ---> 
    <cfset dbPassword  = "Hx41SYUrmnFPa31QCH1ArCHN1YOF8IAL">
    <cfset finalText   = replace(dbPassword, "@@12", "+", "all")>
    <cfset theKey      = "abcdefgh">
    <cfset hashedKey   = hash( theKey, "md5" )>
    ....