Код шифрования PHP преобразован в ColdFusion

У меня есть часть PHP, которую я хотел бы сделать эквивалентной в ColdFusion.

function & _encryptMessage( $message ) {

   $td = mcrypt_module_open( MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CBC, '');
   mcrypt_generic_init( $td, $this->key, $this->iv );
   $encrypted_data = mcrypt_generic( $td, $message );
 mcrypt_generic_deinit($td);
 mcrypt_module_close($td);

   return base64_encode( $encrypted_data );
}

Я думаю, это просто

encrypt(message,"","AES","Base64")

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

ОБНОВЛЕНИЕ: для информации этот ответ от Mister Dai был особенно полезен.

Таким образом, MCRYPT_RIJNDAEL_256 на самом деле означает размер блока, а не силу шифрования. Сила шифрования по-прежнему равна 256, так как ключ и соль генерируются в PHP с использованием значения, которое хешируется с помощью sha-256.

Это вызов шифрования, который у меня есть сейчас:

encrypt(arguments.messageXML,instance.key,"AES/CBC/PKCS5Padding","Base64",ivSalt)

К сожалению, это не работает, потому что ivSalt имеет длину 32 байта (256 бит), а AES ожидает только 16-байтовую соль iv. Глядя здесь может показаться, что максимальный размер блока в ColdFusion/Java для AES — 16 байт (128 бит). Кажется, я не понимаю, как я могу получить размер блока 256 бит. Любая помощь будет принята с благодарностью.


person Stephen Moretti    schedule 27.04.2011    source источник
comment
Когда вы запускаете два, используя одно и то же сообщение, вы получаете тот же результат?   -  person Dave Long    schedule 27.04.2011
comment
Я согласен с Дэйвом. Но несколько вещей, которые бросаются в глаза: 1) ваш encrypt() key отсутствует/пусто 2) вы не передаете iv и 3) шифрование mode должно совпадать с используемым php   -  person Leigh    schedule 27.04.2011
comment
Ах... Я только что вспомнил кое-что о PHP. this-›key аналогичен this.key в ColdFusion. Поэтому мне нужно покопаться в остальной части PHP-файла в поисках ключа и соли IV, что должно помочь мне лучше понять это.   -  person Stephen Moretti    schedule 28.04.2011
comment
Что касается проверки того, дают ли они один и тот же результат; Я бы с удовольствием, но у меня нет установки PHP.   -  person Stephen Moretti    schedule 28.04.2011
comment
@Stephen Moretti - вам также нужно будет изменить mode. IIRC CF по умолчанию имеет значение ECB, а пример php, похоже, использует CBC   -  person Leigh    schedule 28.04.2011
comment
@Stephen, не забудьте посолить шифрование, например. с отметкой времени для защиты от атак радужного стола.   -  person Johan    schedule 28.04.2011
comment
@Stephen Morretti - Если 256 поддерживается только для Rijndael, а не для AES, вы можете попробовать реализацию RijndaelEngine от Bouncy Castle bouncycastle.org /спецификации.html   -  person Leigh    schedule 30.04.2011


Ответы (2)


Прежде чем я отвечу на свой вопрос, следует поблагодарить пару благодарностей. Спасибо Дэйву Бойеру (мистер Дай), Джейсона Дина и Джейсона Делмора за помощь.

Как предложил Ли, мне пришлось использовать Bouncy Castle, облегченный API и шифровальный движок Rijndael.

В итоге я получил функцию для создания шифра rijndael и функции для шифрования и дешифрования строки с помощью ключа и ivsalt.

<cfcomponent displayname="Bounce Castle Encryption Component" hint="This provides bouncy castle encryption services" output="false">

<cffunction name="createRijndaelBlockCipher" access="private">
    <cfargument name="key" type="string" required="true" >
    <cfargument name="ivSalt" type="string" required="true" >
    <cfargument name="bEncrypt" type="boolean" required="false" default="1">
    <cfargument name="blocksize" type="numeric" required="false" default=256>
    <cfscript>
    // Create a block cipher for Rijndael
    var cryptEngine = createObject("java", "org.bouncycastle.crypto.engines.RijndaelEngine").init(arguments.blocksize);

    // Create a Block Cipher in CBC mode
    var blockCipher = createObject("java", "org.bouncycastle.crypto.modes.CBCBlockCipher").init(cryptEngine);

    // Create Padding - Zero Byte Padding is apparently PHP compatible.
    var zbPadding = CreateObject('java', 'org.bouncycastle.crypto.paddings.ZeroBytePadding').init();

    // Create a JCE Cipher from the Block Cipher
    var cipher = createObject("java", "org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher").init(blockCipher,zbPadding);

    // Create the key params for the cipher     
    var binkey = binarydecode(arguments.key,"hex");
    var keyParams = createObject("java", "org.bouncycastle.crypto.params.KeyParameter").init(BinKey);

    var binIVSalt = Binarydecode(ivSalt,"hex");
    var ivParams = createObject("java", "org.bouncycastle.crypto.params.ParametersWithIV").init(keyParams, binIVSalt);

    cipher.init(javaCast("boolean",arguments.bEncrypt),ivParams);

    return cipher;
    </cfscript>
</cffunction>

<cffunction name="doEncrypt" access="public" returntype="string">
    <cfargument name="message" type="string" required="true">
    <cfargument name="key" type="string" required="true">
    <cfargument name="ivSalt" type="string" required="true">

    <cfscript>
    var cipher = createRijndaelBlockCipher(key=arguments.key,ivSalt=arguments.ivSalt);
    var byteMessage = arguments.message.getBytes();
    var outArray = getByteArray(cipher.getOutputSize(arrayLen(byteMessage)));
    var bufferLength = cipher.processBytes(byteMessage, 0, arrayLen(byteMessage), outArray, 0);
    var cipherText = cipher.doFinal(outArray,bufferLength);

    return toBase64(outArray);
    </cfscript>
</cffunction>


<cffunction name="doDecrypt" access="public" returntype="string">
    <cfargument name="message" type="string" required="true">
    <cfargument name="key" type="string" required="true">
    <cfargument name="ivSalt" type="string" required="true">

    <cfscript>
    var cipher = createRijndaelBlockCipher(key=arguments.key,ivSalt=arguments.ivSalt,bEncrypt=false);
    var byteMessage = toBinary(arguments.message);
    var outArray = getByteArray(cipher.getOutputSize(arrayLen(byteMessage)));
    var bufferLength = cipher.processBytes(byteMessage, 0, arrayLen(byteMessage), outArray, 0);
    var originalText = cipher.doFinal(outArray,bufferLength);

    return createObject("java", "java.lang.String").init(outArray);
    </cfscript>
</cffunction>

<cfscript>
function getByteArray(someLength)
{
    byteClass = createObject("java", "java.lang.Byte").TYPE;
    return createObject("java","java.lang.reflect.Array").newInstance(byteClass, someLength);
}
</cfscript>

</cfcomponent>

Функции doEncrypt и doDecrypt общедоступны, но не функция, создающая шифр rijndael. Функции шифрования и дешифрования принимают строку, ключ и ivSalt, возвращая соответственно зашифрованную или расшифрованную строку.

createRijndaelBlockCipher принимает ключ ivSalt, логическое значение, указывающее, будет ли шифр использоваться для шифрования или дешифрования, и размер блока, хотя размер блока по умолчанию равен 256 битам. Функция довольно хорошо прокомментирована, поэтому она должна иметь смысл.

UDF внизу (особая благодарность Джейсону Делмору за этот самородок) гарантирует, что ColdFusion правильно создаст массив байтов для расшифровки. Некоторые другие способы создания массивов байтов просто не работают или приводят к несогласованным результатам в ошибках расшифровки или повреждения буфера буфера.

Вот об этом на самом деле. Потребовалось слишком много усилий, когда стандартное шифрование AES использует 128-битные блоки, а 128-битные ключи предназначены для классификации до СЕКРЕТНО, 192-битные или выше для СОВЕРШЕННО СЕКРЕТНО. 256-битные блоки и 256-битные ключи — это немного больше. То, что вы можете, не означает, что вы должны.

Помните, что MCRYPT_RIJNDAEL_256 — это размер блока, а не уровень шифрования. Уровень шифрования задается силой ключа, который вы передаете в mcrypt_encrypt, и увеличение размера блока не увеличивает силу шифрования.

person Stephen Moretti    schedule 03.05.2011

http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7c52.html

Вы можете сделать что-то простое, например:

<cfset stringName = "variable 1: " & variable1 & " some more text" />
<cfset varName = HASH(stringName, "SHA") />

или даже это:

<cfset varName = HASH("i want this string to be encrypted", "SHA") />

Обычно я делаю что-то подобное для хранения паролей и других конфиденциальных данных.

Надеюсь, что ссылка и/или примеры помогут, Brds

person Brds    schedule 27.04.2011
comment
Спасибо за это Брдс. Я подозреваю, что в то время как hash зашифрует строку, но мне нужно иметь возможность расшифровать результат. Кроме того, если я не ошибаюсь, hash() не поддерживает AES (RIJNDAEL - это AES, верно?) - person Stephen Moretti; 28.04.2011
comment
Правильно. Hash() не может быть реверсирован/расшифрован, и AES/Rijndael не является поддерживаемым алгоритмом hash, только encrypt(). help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/ - person Leigh; 28.04.2011