Как сопоставить шифрование ColdFusion с Java 1.4.2? - PullRequest
6 голосов
/ 14 апреля 2010

*** сладкое - спасибо Эдварду Смиту за CF Technote, который указал, что ключ от ColdFusion был закодирован в Base64. Смотрите generateKey () для 'fix'

Моя задача - использовать Java 1.4.2 для сопоставления результатов с данным примером кода ColdFusion для шифрования.

Известные / заданные значения:

  • 24-байтовый ключ
  • 16-байтовая соль (IVorSalt)
  • Кодировка Hex
  • Алгоритм шифрования: AES / CBC / PKCS5Padding
  • Пример значения открытого текста
  • Зашифрованное значение образца открытого текста после прохождения кода ColdFusion

Предположения:

  • Количество итераций, не указанных в коде ColdFusion, поэтому я предполагаю, что только одна итерация
  • 24-байтовый ключ, поэтому я предполагаю 192-битное шифрование

Приведенный / работающий пример кода шифрования ColdFusion:

<cfset ThisSalt = "16byte-salt-here">
<cfset ThisAlgorithm = "AES/CBC/PKCS5Padding">
<cfset ThisKey = "a-24byte-key-string-here">
<cfset thisAdjustedNow = now()>
<cfset ThisDateTimeVar = DateFormat( thisAdjustedNow , "yyyymmdd" )>
<cfset ThisDateTimeVar = ThisDateTimeVar & TimeFormat( thisAdjustedNow , "HHmmss" )>
<cfset ThisTAID = ThisDateTimeVar & "|" & someOtherData>
<cfset ThisTAIDEnc = Encrypt( ThisTAID , ThisKey , ThisAlgorithm , "Hex" , ThisSalt)>

Мой код шифрования / дешифрования Java 1.4.2:

package so.example;

import java.security.*;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.*;

public class SO_AES192 {

private static final String _AES = "AES";
private static final String _AES_CBC_PKCS5Padding = "AES/CBC/PKCS5Padding";
private static final String KEY_VALUE = "a-24byte-key-string-here";
private static final String SALT_VALUE = "16byte-salt-here";
private static final int ITERATIONS = 1;

private static IvParameterSpec ivParameterSpec;

public static String encryptHex(String value) throws Exception {
    Key key = generateKey();

    Cipher c = Cipher.getInstance(_AES_CBC_PKCS5Padding);
    ivParameterSpec = new IvParameterSpec(SALT_VALUE.getBytes());
    c.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);

    String valueToEncrypt = null;
    String eValue = value;
    for (int i = 0; i < ITERATIONS; i++) {
//            valueToEncrypt = SALT_VALUE + eValue; // pre-pend salt - Length > sample length
        valueToEncrypt =  eValue;     // don't pre-pend salt  Length = sample length
        byte[] encValue = c.doFinal(valueToEncrypt.getBytes());
        eValue =  Hex.encodeHexString(encValue);
    }
    return eValue;
}

public static String decryptHex(String value) throws Exception {
    Key key = generateKey();

    Cipher c = Cipher.getInstance(_AES_CBC_PKCS5Padding);
    ivParameterSpec = new IvParameterSpec(SALT_VALUE.getBytes());
    c.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);

    String dValue = null;
    char[] valueToDecrypt = value.toCharArray();
    for (int i = 0; i < ITERATIONS; i++) {
        byte[] decordedValue = Hex.decodeHex(valueToDecrypt);
        byte[] decValue = c.doFinal(decordedValue);
//            dValue = new String(decValue).substring(SALT_VALUE.length()); // when salt is pre-pended
        dValue = new String(decValue);   // when salt is not pre-pended
        valueToDecrypt = dValue.toCharArray();
    }
    return dValue;
}

private static Key generateKey() throws Exception {
    // Key key = new SecretKeySpec(KEY_VALUE.getBytes(), _AES); // this was wrong
    Key key = new SecretKeySpec(new BASE64Decoder().decodeBuffer(keyValueString), _AES); // had to un-Base64 the 'known' 24-byte key.
    return key;
}

}

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

Я не очень разбираюсь в криптовалютах, но думаю, что смогу взять образец открытого текста и создать такое же зашифрованное значение в Java, как и ColdFusion. Я могу зашифровать / расшифровать свои собственные данные с помощью своего кода Java (поэтому я согласен), но я не могу ни сопоставить, ни расшифровать зашифрованное значение образца ColdFusion.

У меня есть доступ к локальному веб-сервису, который может проверить зашифрованный вывод. Данный выходной образец ColdFusion хорошо проходит / дешифрует (конечно). Если я пытаюсь расшифровать тот же пример с помощью моего Java-кода (используя фактический ключ и соль), я получаю ошибку «Данный последний блок не заполнен должным образом». Я получаю тот же чистый результат, когда передаю свою попытку шифрования (используя действительный ключ и соль) тестовой веб-службе.

Есть идеи?

1 Ответ

4 голосов
/ 14 апреля 2010

Это значение в Coldfusion ThisKey:

<cfset ThisKey = "a-24byte-key-string-here">

Точно такая же строка, которая возвращается из функции java generateKey ()? Я считаю, что они должны быть одной строкой, чтобы сгенерированный зашифрованный текст был одинаковым.

Чтобы использовать фиксированный ключ, подобный тому, что используется в CF, вам может потребоваться следовать этому из CF technote для надежного шифрования:

Вы можете создать свой собственный ключ по двум причинам:

  1. Вы хотите сопоставить данные других программ шифрования.
  2. Вы хотите повысить устойчивость к взлому зашифрованные данные по шаблону методы криптоанализа.

Например, чтобы создать 32-байтовый ключ использовать с алгоритмом AES с шестнадцатеричное значение:

8738fed68e7677d374e0946c8f7bd3bb4f50f23717f9f3667b2419483959039c

вы бы использовали функции ColdFusion BinaryDecode и ToBase64 для создания ключ:

<cfset myKey =
ToBase64(BinaryDecode("8738fed68e7677d374e0946c8f7bd3bb4f50f23717f9f3667b2419483959039c","Hex")>
<cfset encrypted =Encrypt(myString, myKey, "AES")>

РЕДАКТИРОВАТЬ: только что понял, что ключ (как вы упоминали в своем комментарии) является base64, поэтому, если метод «generateKey» в Java выглядит следующим образом:

private static Key generateKey() throws Exception {
final byte[] decodedKey = new BASE64Decoder().decodeBuffer(KEY_VALUE);
final Key key = new SecretKeySpec(decodedKey, _AES);
return key;
}

Ты должен быть золотым.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...