Допустим у нас есть данные:
$data = 'My secret data!';
И мы хотим зашифровать их, чтобы позже расшифровать с использованием пароля, например такого:
$password = '1234';
Но открытый пароль мы не будем передавать, а создадим на его основе ключ с помощью хеширования и передадим его.
$key = sha1($password);
Рекомендуется использовать для шифрования библиотеку OpenSSL: openssl_encrypt()
, openssl_decrypt()
и вспомогательные функции.
Для начала нужно выбрать метод шифрования, например, aes-128-cbc
. Все доступные методы можно посмотреть вызвав функцию openssl_get_cipher_methods()
.
$method = 'aes-128-cbc';
Теперь нам нужно создать вектор инициализации (IV, Initialization Vector) - случайные данные, на основе которых будет произведено шифрование.
// определяем длину iv для выбранного метода шифрования
$ivSize = openssl_cipher_iv_length($method);
// генерируем iv необходимой длины
$iv = openssl_random_pseudo_bytes($ivSize);
Всё готово к шифрованию. Вызываем метод openssl_encrypt()
:
$encrypted = openssl_encrypt(
$data,
$method,
$key,
// передаём флаг OPENSSL_RAW_DATA,
// чтобы openssl не прогнал результат через base64 и вернул его как есть
OPENSSL_RAW_DATA,
$iv
);
Добавляем iv в результат шифрования, чтобы мы могли использовать его при расшифровке:
$encrypted = $iv . $encrypted;
Теперь прогоняем результат через base64:
$encrypted = base64_encode($encrypted); // '4b7zpIa4IsTxiQWOsSCkC89urh/vkFtaG4O9Vcr1uV8='
Зашифрованная строка готова, её мы можем передавать во вне. И когда эта строка придёт к нам, мы сможем её расшифровать.
Декодируем base64:
$encrypted = base64_decode($encrypted);
Теперь получим из строки iv:
// определяем длину iv для выбранного метода шифрования
$ivSize = openssl_cipher_iv_length($method);
// вырезаем iv из зашифрованных данных
$iv = substr($encrypted, 0, $ivSize);
Функция substr
будет корректно работать с битовыми строками только если в настройках php указано mbstring.func_overload = 0
, для остальных вариантов нужно использовать mb_substr
и mb_strlen
, указав кодировку 8bit
для OpenSSL или iso-8859-1
для Mcrypt. Готовый код с переключением на mb_
функции можно взять в моём гитхабе hobocta/encrypt.
Убираем из зашифрованной строки iv:
$encrypted = substr($encrypted, $ivSize);
И вызываем openssl_decrypt()
:
$decrypted = openssl_decrypt(
$encrypted,
$method,
$key,
OPENSSL_RAW_DATA,
$iv
);
Выводим результат:
echo $decrypted; // 'My secret data!'
Если же библиотека OpenSSL недоступна и её никак нельзя установить, то в крайнем случае мы можем использовать аналогичный функционал из библиотеки Mcrypt.
В Mcrypt нам сначала тоже нужно выбрать метод шифрования. Выберем, например, MCRYPT_RIJNDAEL_128
с режимом MCRYPT_MODE_CBC
. Все доступные методы тут, а режимы тут.
$cipher = MCRYPT_RIJNDAEL_128;
$mode = MCRYPT_MODE_CBC;
$ivSource = MCRYPT_RAND; // источник случайных данных
Генерируем iv:
$ivSize = mcrypt_get_iv_size($cipher, $mode);
$iv = mcrypt_create_iv($ivSize, $ivSource);
Шифруем данные:
$encrypted = mcrypt_encrypt(
$cipher,
$key,
$data,
$mode,
$iv
);
Добавляем iv в шифрованные данные и кодируем в base64:
$encrypted = $iv . $encrypted;
$encrypted = base64_encode($encrypted); // 'HJGnojVdzFAQAHYqkwNOd9pfokMMs7GJfN5xAqVguMw='
Для того, чтобы расшифровать нам останется выполнить следующее:
// получаем из данных iv
$iv = substr($encrypted, 0, $ivSize);
// убираем из данных iv
$encrypted = substr($encrypted, $ivSize);
// расшифровываем
$decrypted = mcrypt_decrypt(
$cipher,
$key,
$encrypted,
$mode,
$iv
);
// в результате мы получим данные с двумя лишними символами вконце:
var_export($decrypted); // 'My secret data!' . "\0" . ''
// убираем лишние символы:
$decrypted = rtrim($decrypted, "\0\4");
// всё готово
var_export($decrypted); // 'My secret data!'
Всё это с удобной оберткой можно взять в моём гитхабе: hobocta/encrypt