Расшифровка строки в ColdFusion, зашифрованной с помощью 3DES в C # - PullRequest
4 голосов
/ 08 февраля 2012

У нас возникают проблемы с расшифровкой строки в 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 и 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#">

UPDATE:

Решение, если вы последуете комментариям, должно было измениться:

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

1 Ответ

5 голосов
/ 09 февраля 2012

Похоже, в вашей функции 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-байтовый ключ для этого алгоритма. Поэтому сначала вы должны хешировать ключ и дополнить его до нужной длины В противном случае decrypt () будет жаловаться, что ключ слишком мал.

    Примечание: CF также ожидает, что последний ключ будет закодирован в base64. Ошибка Невозможно декодировать строку "бла-бла" предполагает, что ваш ключ ввода находится не в 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" )>
.... 
...