我们无法解密之前使用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#">
答案 0 :(得分:5)
在您的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 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" )>
最后,反馈模式必须匹配。由于.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" )>
....