*** сладкий - благодаря Edward Smith для CF Technote, который указал, ключ от ColdFusion был закодированным Base64. См. generateKey () для 'фиксации'
Моя задача состоит в том, чтобы использовать Java 1.4.2 для соответствия результатам данный пример кода ColdFusion для шифрования.
Знать/давать значения:
Предположения:
Давать/работать образец кода шифрования 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;
}
}
Я не могу создать зашифрованную стоимость соответствия, ни дешифровать данное зашифрованное значение. Мое предположение, это - что-то, чтобы сделать с тем, как я обрабатываю начальный вектор/соль.
Я не очень crypto-опытен, но я думаю, что должен смочь взять демонстрационный открытый текст и произвести то же зашифрованное значение в Java как произведенный ColdFusion. Я могу шифровать/дешифровать свои собственные данные с моим кодом Java (таким образом, я последователен), но я не могу соответствовать, ни дешифровать зашифрованное значение образца ColdFusion.
У меня есть доступ к локальному веб-сервису, который может протестировать зашифрованный вывод. Данный выходной образец ColdFusion передает/дешифрует прекрасный (конечно). Если я пытаюсь дешифровать тот же образец со своим кодом Java (использующий фактический ключ и соль), я получаю "Данный заключительный блок не правильно дополненная" ошибка. Я получаю тот же конечный результат, когда я передаю свою попытку шифрования (использующий фактический ключ и соль) к тестовому веб-сервису.
Какие-либо идеи?
Является ли значение в Coldfusion ThisKey:
<cfset ThisKey = "a-24byte-key-string-here">
той же самой строкой, которая возвращается функцией java generateKey ()? Я считаю, что они должны быть одной и той же строкой, чтобы сгенерированный зашифрованный текст был таким же.
Чтобы использовать фиксированный ключ, подобный тому, что используется в CF, вам может потребоваться следовать этому из CF technote по надежному шифрованию:
Вы можете захотеть сгенерировать свой собственный ключ по двум причинам:
- Вы хотите сопоставить детали другого программного обеспечения для шифрования.
- Вы хотите повысить устойчивость к взлому ваших зашифрованных данных с помощью шаблонно-ориентированных методов криптоанализа.
Например, чтобы создать 32-байтовый ключ для использования с алгоритмом AES с шестнадцатеричным значением :
8738fed68e7677d374e0946c8f7bd3bb4f50f23717f9f3667b2419483959039c
, вы должны использовать {1} функции 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;
}
Вы должны быть золотыми.