Шифрование DESede (3DES) в RAILO CFML

Я пытался в течение многих дней, чтобы попытаться решить эту проблему.

Сторонний веб-сервис требует, чтобы я отправлял зашифрованные данные с использованием 3DES с ECB и PKCS7padding — они используют .NET

Функция шифрования в railo CFML ограничена DESede без каких-либо дополнительных опций (т. е. для режима шифрования и заполнения используются значения по умолчанию).

Кто-нибудь сталкивался с этой проблемой в Railo и придумал решение (возможно, на основе Java)? - Я серьезно рву на себе волосы!

Основываясь на предложениях Ли ниже, я внес некоторые изменения:

Я добился некоторого прогресса, я думаю, что этот ключ имеет какое-то хеширование MD5.

Я порылся в Интернете и немного изменил ваше решение - я не думаю, что заполнение необходимо, но результирующая зашифрованная строка сначала выглядит так, как я должен был ожидать, но затем при ближайшем рассмотрении она неверна:

IvParameterSpec = createObject("java", "javax.crypto.spec.IvParameterSpec");
Cipher = createObject("java", "javax.crypto.Cipher");
SecretKeySpec = createObject("java", "javax.crypto.spec.SecretKeySpec");
BASE64Decoder = createObject("java", "sun.misc.BASE64Decoder");
Str = createObject("java", "java.lang.String");
MessageDigest = createObject("java", "java.security.MessageDigest");

input  = "<xml><PanNumber>6280390027626871</PanNumber><Req_Currency_Code>826</Req_Currency_Code><Card_Pin>1234</Card_Pin><Till_Amount></Till_Amount><Auth_Code></Auth_Code></xml>";
key = "06098140901984F95E139F29B479D952CB6545C177D21456";

md = MessageDigest.getInstance("MD5");
md.update(key.getBytes("UTF-8"), 0, key.length());
keyBytes = md.digest();
newKey = tobase64(keyBytes);
keyBytes2  = binaryDecode(newKey, "base64");
keyBytes2  = arrayMerge(keyBytes, arraySlice(keyBytes, 1, 8));
allnewKey = binaryEncode(javacast("byte[]", keyBytes2), "base64");

encrypted = encrypt(input, allnewKey, "desede", "base64");
WriteDump("encrypted (CF): "& encrypted);`

Результат: <сильный> 26sfwv2DHDj7EHYd5Qao8veDtPbKIcv8rDVhbLPDEaWHO27EUGRF6KrdbXe7NBUVADYMdGuagfO4Tev584dUcgKGJ2h6kWPZxooNUGMgL2xB7e00YOkLosA8wFD569sZUd1MGKuF9yCjY1zCsAE4SgohkcuK9YZ7BizQma99 / W9yOsIjAfHtAqGiep4tMTQ + eFASYtPybccsgi8H4brIB / HAu0kaDSAw

Ожидаемый результат: <сильный> 26sfwv2DHDj7EHYd5Qao8veDtPbKIcv8rDVhbLPDEaWHO27EUGRF6MxaAzUpJDqQBq8NGgdqmtn6q / wVQNHGWrOE8 + aetKVC78nszS3ZO8AHjwoT1igv4lGl78n8jCHHU + KwnBT7KfXIYMTCuwO / MohIiFbGyhMXPsvv3 / G4OY1C2nEkN0LweLh4mTgtU8syT1M9XdmvwhaltsmPoFtoE9FujvQpJCY3


person eggwater    schedule 12.05.2012    source источник
comment
(Редактировать) Можете ли вы опубликовать образец ключа и результаты, которые вы получаете в Railo и .net? Я думаю, что Railo просто использует значения по умолчанию для Java, а именно ECB и PKCS5Padding (в основном совместимые с PKCS7padding для 8 байтов). Так что по идее должно работать из коробки.   -  person Leigh    schedule 13.05.2012


Ответы (1)


Функция шифрования в railo CFML ограничена DESede без каких-либо дополнительных опций (т. е. для режима шифрования и заполнения используются значения по умолчанию).

Да, я считаю, что он использует значения по умолчанию для Java, т.е. DESede/ECB/PKCS5Padding, которые совместимы с TripleDES/ECB/PKCS7padding в .NET. Таким образом, он должен работать прямо из коробки, если вы используете 24-байтовый ключ.

Не зная больше, я предполагаю, что это может быть проблема с размером вашего ключа. .NET поддерживает как 16-, так и 24-байтовые ключи, но java поддерживает только 24-байтовые ключи. Поэтому, если ваш ключ имеет длину всего 16 байт, вам нужно дополнить его первыми восемью (8) байтами, чтобы сделать его приемлемым для Java/Railo.

Код CF/Railo

<cfscript>
    input  = "DESede (3DES) Encryption in RAILO CFML";
    key    = "ru8femXhTm9jwdGdhb/4Sw==";

    // pad the key with the first eight bytes. then convert back to base64
    keyBytes  = binaryDecode(key, "base64");
    keyBytes  = arrayMerge(keyBytes, arraySlice(keyBytes, 1, 8));
    newKey = binaryEncode(javacast("byte[]", keyBytes), "base64");

    encrypted = encrypt(input, newKey, "desede", "base64");
    WriteDump("encrypted (CF): "& encrypted);
</cfscript>

Код C#

byte[] input = Encoding.UTF8.GetBytes("DESede (3DES) Encryption in RAILO CFML");
byte[] key = Convert.FromBase64String("ru8femXhTm9jwdGdhb/4Sw==");

TripleDESCryptoServiceProvider algorithm = new TripleDESCryptoServiceProvider();
algorithm.Mode = CipherMode.ECB;
algorithm.BlockSize = 64;
algorithm.KeySize = 128; // 16 byte key
algorithm.Key = key;
ICryptoTransform cipher = algorithm.CreateEncryptor();
byte[] encrypted = cipher.TransformFinalBlock(input, 0, input.Length);
Console.WriteLine("encrypted (.NET): {0}", Convert.ToBase64String(encrypted));

Результаты:

encrypted (CF):   fMPlk0ZqHDwp2zzZs/Cng7Y6r8Acr55UPJYWJTruEesxkBApsEFo6w==
encrypted (.NET): fMPlk0ZqHDwp2zzZs/Cng7Y6r8Acr55UPJYWJTruEesxkBApsEFo6w==

Обновление: странно. Когда я MD5 хэширую ключ в .NET, я получаю ваш первый результат, а не «ожидаемый результат».

    String rawInput = "<xml><PanNumber>6280390027626871</PanNumber><Req_Currency_Code>826</Req_Currency_Code><Card_Pin>1234</Card_Pin><Till_Amount></Till_Amount><Auth_Code></Auth_Code></xml>";
    String rawKey = "06098140901984F95E139F29B479D952CB6545C177D21456";
    byte[] input = Encoding.UTF8.GetBytes(rawInput);
    byte[] key = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(rawKey));
    // ... rest of code 

Результат:

encrypted (.NET): 26sfwv2DHDj7EHYd5Qao8veDtPbKIcv8rDVhbLPDEaWHO27EUGRF6KrdbXe7NB
UVADYMdGuagfO4Tev584dUcgKGJ2h6kWPZxooNUGMgL2xB7e00YOkLosA8wFD569sZUd1MGKuF9yCjY1
zCsAE4SgohkcuK9YZ7BizQma99/W9yOsIjAfHtAqGiep4tMTQ+eFASYtPybccsgi8H4brIB/HAu0kaDS
Aw          
person Leigh    schedule 13.05.2012
comment
Спасибо Ли - ключ, который мне прислали для тестирования, если это поможет, я думаю, что он должен быть 24-байтовым: 06098140901984F95E139F29B479D952CB6545C177D21456. - person eggwater; 13.05.2012
comment
и единственный способ получить от этого результат (хотя и не соответствующий результату C#) — преобразовать ключ с помощью следующей функции: newKey=toBase64(binarydecode("06098140901984F95E139F29B479D952CB6545C177D21456","hex")) - person eggwater; 13.05.2012
comment
Я добился некоторого прогресса, я думаю, что этот ключ имеет какое-то хеширование MD5. - person eggwater; 13.05.2012
comment
измененный исходный вопрос выше. - person eggwater; 13.05.2012
comment
(Извините за задержку с ответом. Я был занят весь день.) Какие именно инструкции вы получили о том, как зашифровать строку? Они действительно упоминали хеширование? - person Leigh; 14.05.2012
comment
Я попробовал это в .NET (сначала хешировал ключ MD5) и получил результат Railo, а не ожидаемый результат. Смотрите мой обновленный ответ. - person Leigh; 14.05.2012
comment
Еще раз спасибо Ли. Какой результат вы получили в .NET без хеширования? Сегодня мне придется поговорить с третьей стороной, чтобы спросить о хешировании. Мне сказали, что ключ 24 байта, но я не могу заставить его играть, не манипулируя им. - person eggwater; 14.05.2012
comment
Спасибо за вашу помощь, Ли, я думаю, что исправил это сейчас. Теперь с вашим дополнением и хешированием он дает желаемый результат. - person eggwater; 14.05.2012