对用C#中的3DES加密的ColdFusion中的字符串进行解密

本文关键字:字符串 解密 ColdFusion 中的 3DES 加密 对用 | 更新日期: 2023-09-27 18:23:52

我们在ColdFusion中解密之前使用3DES和C#加密的字符串时遇到困难。这是我们最初用来加密字符串的代码:

    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加密-.NET和ColdFusion不玩漂亮的

运气不佳。这是我们的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)>

返回错误:尝试加密或解密输入字符串时出错:"无法解码字符串"blablah"

因此,看起来它试图解密密钥而不是字符串,但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#">

对用C#中的3DES加密的ColdFusion中的字符串进行解密

看起来您的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字节的密钥。因此,您必须首先对密钥进行散列,并将其填充到适当的长度。否则,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。


更新:

我用一个任意的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" )>
....