PHP: mcrypt меняет начало строки в мусор - PullRequest
2 голосов
/ 24 августа 2009

Мне нужно среднее или сильное шифрование на стороне сервера, поэтому я решил использовать mcrypt с PHP. Если я использую функции ниже, начало моей исходной строки превращается в двоичный мусор после расшифровки. (Это не обычная проблема получения добавленного дополнительного мусора, вместо этого моя строка изменена .) Согласно документации, mcrypt_encrypt () должно иметь достаточно дополненных символов, чтобы соответствовать размеру блока выбранного алгоритма, но я подозреваю, что он не работает.

Однако, если я дополню его вручную до размера блока 128 бит (16 байт) Rijndael, это тоже не сработает. Единственный способ заставить это работать - это добавить некоторую строку достаточно долго, чтобы (вероятно) покрыть выделенный блок и добавить известный префикс, такой как «DATA #», между этой строкой и моими данными. После расшифровки этот блок был частично искажен, но мой префикс и все данные после него были правильно расшифрованы.

$GLOBALS['encryptionmarker'] = 'DATA#';

function encrypt($plain, $key) {
    /*
    // workaround because beginning of decrypted string is being mangled
    // so we simply prefix with some text plus marker
    $prefix = str_pad('', 128, '#', STR_PAD_RIGHT).$GLOBALS['encryptionmarker'];
    $plain = $prefix.$plain;
    */

    $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $plain, MCRYPT_MODE_CFB,
        mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB),
        MCRYPT_DEV_URANDOM));

    return $encrypted;
}

function decrypt($encrypted, $key) {
    $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted, MCRYPT_MODE_CFB,
        mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB),
        MCRYPT_DEV_URANDOM));

    /*
    // workaround: remove garbage
    $pos = strpos($decrypted, $GLOBALS['encryptionmarker']);
    $decrypted = trim(substr($decrypted, $pos + strlen($GLOBALS['encryptionmarker'])));
    */

    return $decrypted;
}

Что не так с моими функциями? Почему я должен так ставить префикс моих данных (я считаю это грязным обходным путем, поэтому я бы хотел это исправить)?

Хранение зашифрованных данных не является проблемой; дешифрование сразу после шифрования без сохранения в базе данных приводит к тем же ошибкам.

Ответы [ 2 ]

5 голосов
/ 24 августа 2009

Ваша проблема в том, что вы генерируете новый, другой, случайный IV на принимающей стороне. Это не работает, как вы видели.

Получатель должен знать IV, который использовал отправитель; поэтому вы должны отправить его вместе с зашифрованными данными и передать его mcrypt_decrypt().

Обратите внимание, что вы также должны использовать mhash() с ключом (ключом, отличным от ключа шифрования) для создания HMAC над сообщением и проверки его на принимающей стороне. Если вы этого не сделаете, человек в середине может тривиально изменить части вашего сообщения, не обнаруживая его.

2 голосов
/ 24 августа 2009

Используйте один и тот же IV для расшифровки и расшифровки. IV не является общим секретом, но должен быть передан. Вы можете проконсультироваться Википедия: IV

$IV = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB),
      MCRYPT_DEV_URANDOM));

IV должен быть передан ОДИН РАЗ. Вы можете увеличить значение IV для каждого пакета. Но это можно сделать обеими сторонами независимо друг от друга.

...