在 C# 中解密使用 3DES 加密的 ColdFusion 中的字符串
我们在 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;
}
我们尝试使用此处的建议:
三重 DES 加密 - .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)>
返回错误:尝试加密或解密输入字符串时发生错误:'' 无法解码字符串“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#">
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
看起来您的 C# 函数中需要处理一些额外的问题才能实现兼容性:
.NET 函数修改加密字符串。你需要
反转这些更改,以便解密将其识别为有效的 base64:
该函数还使用创建 16 字节密钥的哈希。 CF/java 需要 24 字节密钥。因此,您必须首先对密钥进行哈希处理,然后将其填充到适当的长度。否则,decrypt() 会抱怨密钥太小。
注意:CF 还期望最终密钥采用 Base64 编码。错误无法解码字符串“blahblah”表明您的输入密钥不是 base64 格式。
最后,反馈模式必须匹配。由于 .NET 代码使用安全性较低的
ECB
模式,因此 CF 代码也必须使用该模式。另一个需要注意的问题是编码。在 CF 中,加密/解密始终将输入字符串解释为 UTF8,而 .NET 函数使用 ASCII。为了完全兼容,双方应使用相同的编码,在本例中为 UTF8。
更新:
我使用任意 8 个字符密钥(而不是 Base64 字符串)测试了上述内容,CF9 仍然正确解密了该字符串。
Looks like there a few extra twists in your c# function you need to handle to achieve compatibility:
The .NET function modifies the encrypted string. You need to
reverse those changes so decrypt will recognize it as valid base64:
The function also uses a hash which creates a 16 byte key. CF/java require a 24 byte key for that algorithm. So you must first hash the key and pad it to the proper length. Otherwise, decrypt() will complain the key is too small.
Note: CF also expects the final key to be base64 encoded. The error Can not decode string "blahblah" suggests your input key is not in base64.
Finally, the feedback modes must match. Since the .NET code uses the less secure
ECB
mode, the CF code must use that mode as well.One other issue to watch out for is encoding. In CF, encrypt/decrypt always interpret the input string as UTF8, whereas the .NET function uses ASCII. For full compatibility, both sides should use the same encoding, in this case UTF8.
Update:
I tested the above with an arbitrary 8 character key (instead of a base64 string) and CF9 still decrypted the string properly.