【问题标题】:Decrypting a string in ColdFusion encrypted with 3DES in C#在 C# 中解密用 3DES 加密的 ColdFusion 中的字符串
【发布时间】:2012-02-08 15:22:59
【问题描述】:

我们很难在 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 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#">

更新:

如果你遵循 cmets 的解决方案是改变:

<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#">

【问题讨论】:

  • DESede/CBC/PKCS5Padding 不是有效算法。如果您安装了 ColdFusion 标准版,那么您可以使用以下内容:CFMX_COMPAT、AES、BLOWFISH、DES 和 DESEDE。如果您有 Enterprise,那么您还有 DES-EDE、DESX、RC2、RC4、RC5 和 PBE。所以我会尝试 DESEDE。
  • 如果这不起作用,请尝试在 CF 中对其进行加密,看看是否会产生与 C# 相同的问题,因为有时这些问题是空格或大写,因为算法肯定与我的相同让 C# 和 CF 多次通信加密字符串。
  • 当我们在 DESEDE 中替换时,不幸的是,我们得到了完全相同的错误。
  • @baynezy - “DESede/CBC/PKCS5Padding”完全有效。 CF 允许单独使用算法名称,或算法 + 反馈模式 + 填充方案。

标签: c# asp.net coldfusion 3des


【解决方案1】:

看起来您的 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 byte key 用于该算法。所以你必须首先散列密钥和pad it to the proper length。否则,decrypt() 会抱怨密钥太小。

    注意:CF 还期望最终密钥是 base64 编码的。错误 Can not decode string "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" )>
.... 

【讨论】:

  • 哇,我很感激你为调试这个付出的努力!这无疑揭示了我们的问题。但是,在应用您的建议后,我们遇到了此错误“尝试加密或解密您的输入字符串时发生错误:未正确填充最终块。”由于我们的原始密钥只有 8 个字符长,这可能是问题所在吗?我们需要 16 的最小密钥长度吗?
  • 很有可能,因为这个长度听起来很奇怪。 (上面的密钥由TripleDESCryptoServiceProvider 生成,在 CF 中运行良好)。你能生成一个样本keyencrypted 值供我测试吗?另外,您的密钥是如何生成的?
  • 我们的密钥实际上只是一个 8 个字符的字符串,因此我们可以轻松地在两个应用程序之间共享它。
  • 所以 any 8 个字符串,即“abcdefgh”?这听起来更像是 DES。
  • 很确定我们使用的是 3DES,基于我在顶部的 .net 函数?虽然我承认对加密知之甚少(显然)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-20
  • 1970-01-01
  • 1970-01-01
  • 2013-04-17
  • 1970-01-01
  • 2016-03-19
相关资源
最近更新 更多