对用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#函数中有一些额外的曲折需要处理才能实现兼容性:
-
.NET函数修改加密的字符串。你需要反转这些更改,这样解密就会将其识别为有效的base64:
<!--- reverse replacements in encrypted text ie #DB.Password# ---> <cfset dbPassword = "uAugP@@12aP4GGBOLCLRqxlNPL1PSHfTNEZ"> <cfset finalText = replace(dbPassword, "@@12", "+", "all")>
-
该函数还使用一个散列来创建一个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" )>
-
最后,反馈模式必须匹配。由于.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#">
-
另一个需要注意的问题是编码。在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" )>
....