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

Rob*_*uer 4 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;
    }
Run Code Online (Sandbox Code Playgroud)

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

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)>
Run Code Online (Sandbox Code Playgroud)

返回错误:尝试加密或解密输入字符串时发生错误:''无法解码字符串"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#">
Run Code Online (Sandbox Code Playgroud)

更新:

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

<cfset hashedKey   = hash( theKeyInBase64, "md5" )>
Run Code Online (Sandbox Code Playgroud)

至:

<cfset hashedKey   = hash( theKey, "md5" )>
Run Code Online (Sandbox Code Playgroud)

最终的代码是这样的:

<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#">
Run Code Online (Sandbox Code Playgroud)

Lei*_*igh 5

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

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

    <!--- reverse replacements in encrypted text ie #DB.Password# --->
    <cfset dbPassword = "uAugP@@12aP4GGBOLCLRqxlNPL1PSHfTNEZ">
    <cfset finalText = replace(dbPassword, "@@12", "+", "all")>
    
    Run Code Online (Sandbox Code Playgroud)
  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" )>
    
    Run Code Online (Sandbox Code Playgroud)
  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#">
    
    Run Code Online (Sandbox Code Playgroud)
  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" )>
.... 
Run Code Online (Sandbox Code Playgroud)