Использование PHP Mcrypt с Rijndael / AES - PullRequest
8 голосов
/ 19 июня 2011

Я пытаюсь зашифровать некоторые текстовые сообщения, используя mcrypt из php и шифр Rijndael, но я не уверен насчет MCRYPT_MODE_modename (согласно руководству по PHP это доступны "ecb", "cbc", "cfb", "ofb"," nofb "или" stream ", но я читал, что на самом деле есть еще несколько).Я понятия не имею, что каждый из них делает или как их использовать.

Я прочитал две вещи, что режим ECB не должен использоваться, и MCRYPT_RAND также нет.Они не объяснили почему.Для режима ECB я предполагаю, что это потому, что он всегда генерирует один и тот же зашифрованный вывод для одного и того же простого текста (возможно, это может быть использовано для атаки), понятия не имею о MCRYPT_RAND (упомянуто @azz здесь ).

Мой вопрос, , какой режим mcrypt мне следует использовать, и было бы здорово увидеть пример кода php, использующего it, потому что все примеры, которые я нашел, используют ECB.Строки, которые я пытаюсь зашифровать, будут содержать только текст ascii и переменную длину, не превышающую 500 символов.

Ответы [ 2 ]

16 голосов
/ 19 июня 2011

ecb является самым простым и имеет недостатки, поэтому его не рекомендуется (http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation). cbc считается значительно более сильным, чем ecb. Некоторые другие могут быть даже сильнее, чем cbc, но все они связаны с потоком, поэтому cbc должен соответствовать ваши потребности.

С ... http://us.php.net/manual/en/mcrypt.constants.php...

  • MCRYPT_MODE_ECB (электронная кодовая книга) подходит для случайных данных, таких как шифрование других ключей. Поскольку данные там короткие и случайные, недостатки ЕЦБ имеют благоприятный негативный эффект.
  • MCRYPT_MODE_CBC (цепочка блоков шифрования) особенно подходит для шифрования файлов, когда безопасность значительно увеличивается по сравнению с ECB.
  • MCRYPT_MODE_CFB (шифрованная обратная связь) является лучшим режимом для шифрования потоков байтов, где необходимо зашифровать отдельные байты.
  • MCRYPT_MODE_OFB (выходная обратная связь, в 8 битах) сопоставима с CFB, но может использоваться в приложениях, где распространение ошибок не допускается. Он небезопасен (поскольку работает в 8-битном режиме), поэтому его не рекомендуется использовать.
  • MCRYPT_MODE_NOFB (выходная обратная связь в nbit) сопоставима с OFB, но более безопасна, поскольку работает с размером блока алгоритма.
  • MCRYPT_MODE_STREAM - это дополнительный режим, включающий некоторые потоковые алгоритмы, такие как «WAKE» или «RC4».

Я не уверен, почему MCRYPT_RAND рекомендуется использовать, но это может быть потому, что системный генератор случайных чисел во многих системах не считается действительно случайным. Есть только две альтернативы, и они могут быть недоступны в зависимости от вашей системы и версии PHP. С ... http://php.net/manual/en/function.mcrypt-create-iv.php...

  • Источником IV может быть MCRYPT_RAND (системный генератор случайных чисел), MCRYPT_DEV_RANDOM (чтение данных из / dev / random) и MCRYPT_DEV_URANDOM (чтение данных из / dev / urandom). До версии 5.3.0 MCRYPT_RAND был единственным, поддерживаемым в Windows.

Приведенный ниже код является просто быстрым примером. Это работает, но я не могу засвидетельствовать его силу.


<?php

// Test code

    $objEncManager = new DataEncryptor();

    $sensitiveData = "7890";
    echo "Raw Data: _" . $sensitiveData . "_<br><br>";

    $encryptedData = $objEncManager->mcryptEncryptString( $sensitiveData );
    echo "Enc Data: _" . $encryptedData . "_<br><br>";
    echo "Enc Data length: " . strlen( $encryptedData) . "<br><br>";

    $decryptedData = $objEncManager->mcryptDecryptString( $encryptedData, $objEncManager->lastIv );
    echo "D-enc Data: _" . $decryptedData . "_<br><br>";

    echo "IV: _" . $objEncManager->lastIv . "_<br><br>";


/*
 * Note: These functions do not accurately handle cases where the data 
 * being encrypted have trailing whitespace so the data
 *       encrypted by them must not have any. Leading whitespace is okay.
 *  
 * Note: If your data needs to be passed through a non-binary safe medium you should
 * base64_encode it but this makes the data about 33% larger.
 * 
 * Note: The decryption IV must be the same as the encryption IV so the encryption
 * IV must be stored or transmitted with the encrypted data.
 * From (http://php.net/manual/en/function.mcrypt-create-iv.php)... 
 * "The IV is only meant to give an alternative seed to the encryption routines. 
 * This IV does not need to be secret at all, though it can be desirable. 
 * You even can send it along with your ciphertext without losing security."
 * 
 * Note: These methods don't do any error checking on the success of the various mcrypt functions
 */
class DataEncryptor
{
    const MY_MCRYPT_CIPHER        = MCRYPT_RIJNDAEL_256;
    const MY_MCRYPT_MODE          = MCRYPT_MODE_CBC;
    const MY_MCRYPT_KEY_STRING    = "1234567890-abcDEFGHUzyxwvutsrqpo"; // This should be a random string, recommended 32 bytes

    public  $lastIv               = '';


    public function __construct()
    {
        // do nothing
    }


    /**
     * Accepts a plaintext string and returns the encrypted version
     */
    public function mcryptEncryptString( $stringToEncrypt, $base64encoded = true )
    {
        // Set the initialization vector
            $iv_size      = mcrypt_get_iv_size( self::MY_MCRYPT_CIPHER, self::MY_MCRYPT_MODE );
            $iv           = mcrypt_create_iv( $iv_size, MCRYPT_RAND );
            $this->lastIv = $iv;

        // Encrypt the data
            $encryptedData = mcrypt_encrypt( self::MY_MCRYPT_CIPHER, self::MY_MCRYPT_KEY_STRING, $stringToEncrypt , self::MY_MCRYPT_MODE , $iv );

        // Data may need to be passed through a non-binary safe medium so base64_encode it if necessary. (makes data about 33% larger)
            if ( $base64encoded ) {
                $encryptedData = base64_encode( $encryptedData );
                $this->lastIv  = base64_encode( $iv );
            } else {
                $this->lastIv = $iv;
            }

        // Return the encrypted data
            return $encryptedData;
    }


    /**
     * Accepts a plaintext string and returns the encrypted version
     */
    public function mcryptDecryptString( $stringToDecrypt, $iv, $base64encoded = true )
    {
        // Note: the decryption IV must be the same as the encryption IV so the encryption IV must be stored during encryption

        // The data may have been base64_encoded so decode it if necessary (must come before the decrypt)
            if ( $base64encoded ) {
                $stringToDecrypt = base64_decode( $stringToDecrypt );
                $iv              = base64_decode( $iv );
            }

        // Decrypt the data
            $decryptedData = mcrypt_decrypt( self::MY_MCRYPT_CIPHER, self::MY_MCRYPT_KEY_STRING, $stringToDecrypt, self::MY_MCRYPT_MODE, $iv );

        // Return the decrypted data
            return rtrim( $decryptedData ); // the rtrim is needed to remove padding added during encryption
    }


}
?>
2 голосов
/ 10 июня 2012

Режим ECB небезопасен, поскольку он не вносит случайности в зашифрованные данные.По сути, это означает, что вы увидите те же шаблоны ввода в выводе (то есть см. Изображение, представленное здесь , это «зашифрованная» версия Tux, логотип Linux).

MT_RAND не считается безопасным, поскольку использует генератор случайных чисел операционной системы (функция PHP * rand()).

Для целей криптографии лучше использовать MCRYPT_DEV_RANDOM (чтение данных из / dev / random) или MCRYPT_DEV_URANDOM (чтение данных из /dev/urandom).

Наиболее используемый и безопасныйРежимы шифрования, доступные в Mcrypt, являются режимами CBC и CTR и подходят для общих случаев использования.Всегда лучше использовать шифрование + аутентификация (то есть шифрование, а затем аутентификация с использованием HMAC).Например, режим CBC без аутентификации зависит от атаки Padding Oracle .

...