Как закодировать php файл

Обновлено: 01.07.2024

Симметричное шифрование – это алгоритм шифрования, в котором используется один и тот же криптографический ключ как для шифрования, так и для расшифровки данных. Рассмотрим на PHP шифрование данных симметричным методом на основе алгоритма AES (Advanced Encryption Standard) – симметричного алгоритма блочного шифрования (размер блока 128 бит, ключ 128/192/256 бит). AES является одним из самых распространённых алгоритмов симметричного шифрования..

PHP шифрование данных AES

Как уже говорилось ранее, для шифровки и расшифровки потребуется ключ шифрования. Это может быть любая строка, но мы для его получения воспользуемся функцией, которая генерирует строку псевдослучайных байт длиной 40, и преобразуем полученный результат в шестнадцатеричное представление:

На экран будет выведен результат следующего вида:

Полученное значение мы будем использовать как секретный ключ шифрования и дешифрования данных (он должен храниться в тайне). Запишем его в переменную $key:

Теперь определим, что мы будем кодировать. Для первого примера возьмем обычную строку:

Мы будем шифровать данные алгоритмом AES с 192 битным ключом:

Все доступные методы шифрования можно посмотреть следующим образом:

Имея данные для шифрования $data, выбранный метод $method и секретный ключ $key в PHP симметричное шифрование данных мы можем осуществить с помощью функции openssl_encrypt:

Выведем на экран результат с помощью var_dump($encrypted):

Опять воспользуемся var_dump($decrypted):

Конечный листинг примера симметричного шифрования/расшифровки данных на PHP будет следующий:

PHP шифрование файлов AES

В PHP шифрование файлов от шифрования данных отличается лишь тем, что содержимое файла сначала необходимо прочитать, проделать с ним необходимые операции, а затем – записать.

Создадим обычный текстовый файл в текущей директории:

Ключ и метод шифрования мы возьмем из предыдущего примера, а данные для кодирования получим из файла aes.txt с помощью функции file_get_contents:

Закодируем содержимое файла и запишем его в новый файл aes-encrypted.txt с помощью функции file_put_contents:

Посмотрим содержимое полученного файла:

Осталось попробовать расшифровать этот файл и записать его:

Конечный листинг симметричного шифрования файла на PHP алгоритмом AES:

Асимметричное шифрование

Асимметричное шифрование отличается от симметричного тем, что для шифровки и расшифровки данных используется не один общий ключ, а два разных. Одним из самых распространенных алгоритмов асимметричного шифрования является RSA (аббревиатура от фамилий Rivest, Shamir и Adleman) — криптографический алгоритм с открытым ключом. В этом алгоритме для шифрования данных используется публичный ключ, а для расшифровки – секретный приватный ключ.

PHP шифрование данных RSA

Для работы с данным алгоритмом нам понадобятся публичный public.crt и приватный private.pem ключ. Получить их можно из консоли с помощью openssl. Сгенерируем пару rsa с ключом 2048 бит на 365 дней (“/C=RU/ST=MO/L=MOSCOW/O=POCKETADMIN/TECH=XX/CN=pocketadmin.tech/emailAddress=”example@pocketadmin.tech – информация о субъекте, который выпустил ключ):

Ещё раз хочу обратить внимание, что сам приватный ключ необходимо хранить в тайне! Непосредственно для шифрования третьим лицам достаточно передать только публичный ключ.

Получаем содержимое файла с публичным ключом и извлекаем сам ключ:

С помощью функции openssl_public_encrypt шифруем данные $data публичным ключом $publicKey. Результат шифрования будет помещен в переменную $encrypted:

В дальнейшем, для расшифровки нам понадобится приватный ключ:

Чтобы расшифровать данные $encrypted приватным ключом $privateKey воспользуемся функцией openssl_private_decrypt. Результат помещается в переменную $decrypted:

Проверим результат с помощью var_dump($decrypted):

Приведем весь код на PHP шифрования данных алгоритмом RSA:

PHP шифрование файлов RSA

Создадим простой текстовый файл, который мы будем шифровать:

Используем публичный и приватный ключ из предыдущего примера. Объявим шифруемый файл, шифрованный и расшифрованный:

По аналогии с предыдущими примерами: получаем публичный ключ $publicKey и с помощью него шифруем содержание файла $file. Результат записываем в $fileEncrypted:

Чтобы расшифровать этот файл: получаем приватный ключ $privateKey, расшифровываем содержимое файла $fileEncrypted. Данные записываем в файл $fileDecrypted:

От переводчика: в процессе программирования никогда не забываю о том, что я опасно некомпетентен в криптографии, и всем советую исходить из этого тезиса (ну, может быть кроме вас и еще вон того крутого парня). Однако, так или иначе, в процессе работы возникают задачи, связанные с защитой данных, и их надо решать. Поэтому я предлагаю вашему вниманию перевод статьи финского разрабочика Timo H, которая показалась мне достаточно интересной и полезной.

Важный update: в комментариях SamDark сделал замечание, что библиотека Mcrypt давно не поддерживается и имеет ряд недоработок, поэтому рекомендуется использовать OpenSSL. Если требуется переписывать имеющийся код, то может помочь эта статья. Кроме того, есть сведения, что Mcrypt может быть удален в PHP7.

Это краткое руководство о том, как избежать распространенных ошибок с симметричным шифрованием на PHP.

Будем рассматривать случай, когда данные обрабатываются на стороне сервера (в частности, шифрование происходит на сервере, а данные могут быть получены, например, от клиента в виде открытого текста, пароля и т.п.), что является типичным случаем для PHP-приложений.

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

Естественно, рекомендации, приведенные здесь, не являются «единственно возможным способом» организации шифрования на PHP. Цель этого руководства — попытаться оставить поменьше места для ошибок и сложных неоднозначных решений.

Функции шифрования в PHP

Используйте расширения Mcrypt или OpenSSL.

Алгоритм шифрования и его режим работы, одноразовый код (вектор инициализации)

Используйте AES-256 в режиме CTR со случайным одноразовым кодом (прим. перев.: nonce). AES это стандарт, поэтому можно использовать функции любого из расширений — Mcrypt или OpenSSL.

Всегда генерируйте новый одноразовый код. При этом вы должны пользоватся криптографически стойким источником случайных чисел. Немного подробнее о генерации случайных чисел читайте ниже. Одноразовый код не является секретом, и может быть конкатенирован с шифротекстом для передачи и последущей расшифровки.

Одноразовый код должен быть длиной 128 бит (16 байт), просто строка байт без какого-либо кодирования.

В расширении Mcrypt AES известен как Rijndael-128 (прим. перев.: несмотря на то, что речь идет про AES-256, это не ошибка. AES-256 != Rijndael-256). В OpenSSL соответственно AES-256-CTR.

Пример использования Mcrypt:

Пример использования OpenSSL:

Убедитесь, что шифрование работает правильно с помощью тестовых векторов (прим. перев.: для AES-256-CTR см. пункт F.5.5 на странице 57).

Аутентификация данных

Всегда проводите проверку подлинности и целостности данных.
Для этого после шифрования используйте MAC. Т.е. сначала данные шифруются, а затем берется HMAC-SHA-256 от полученного шифротекста, включая собственно шифротекст и одноразовый код.

При расшифровке сначала проверте HMAC, используя алгоритм сравнения устойчивый к атакам по времени. Не сравнивайте напрямую $user_submitted_mac и $calculated_mac, используя операторы сравнения == или ===. Лучше даже использовать "двойную проверку HMAC".

Если проверка HMAC удачна, можно безопасно производить расшифровку. Если же HMAC не подходит, немедленно завершайте работу.

Ключи шифрования и аутентификации

В идеале использовать ключи, полученные из криптографически стойкого источника случайности. Для AES-256 необходимы 32 байта случайных данных («сырая» строка – последовательность бит без использования какой-либо кодировки).

Не используйте один и тотже ключ для шифрования и аутентификации. Как сказано выше, необходимо 32 байта на ключ шифрования и 32 байта на ключ аутентификации (HMAC). С помощью PBKDF2 вы можете получить 64 байта из пароля и использовать, скажем, первые 32 байта в качестве ключа шифрования, и остальные 32 байта для ключа аутентификации.

Если у вас пароли хранятся в файле, например, в виде HEX-строки, не перекодируйте их перед тем как «скормить» функциям шифрования. Вместо этого используйте PBKDF2 для преобразования ключей из HEX-кодировки сразу в качественный ключ шифрования или аутентификации. Или используйте SHA-256 с выводом без дополнительного кодирования (просто строка в 32 байта) для хеширования паролей. Использование обычного хеширования паролей дает достаточно энтропии. Подробнее описано в следующих параграфах.

Растяжение ключа

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

Одним из параметров PBKDF2 является количество итераций хеширования. И чем оно выше, тем на большую безопасность ключа можно рассчитывать. Если ваш код работает на 64-битной платформе, используйте SHA-512 в качестве алгоритма хэширования для PBKDF2. В случае 32-битной платформы используйте SHA-256.

Однако, невозможно использовать относительно высокое количество итераций в онлайн-приложенях из-за риска DoS-атаки. Поэтому качество ключа не будет столь высоко, как в оффлайновых приложениях, которые могут позволить себе большое число итераций без такого риска. Как правило, для онлайн-приложений подбирают такое количество итераций хеширования, чтоб PBKDF2 отрабатывал не более 100 мс.

В случае, если вы можете использовать пароли с высокой энтропией, не обязательно проводить «растяжение», как для паролей с низкой энтропией. Например, если вы создаете «главный_ключ_шифрования» и «главный_ключ_аутентификации», используя /dev/urandom, то необходимость в PBKDF2 вообще отпадает. Только убедитесь, что используете ключи как последовательности бит, без какого-либо кодирования.

Кроме того, с помощью PBKDF2 несложно получить оба ключа и для шифрования, и для аутентификации от одного мастер-пароля (просто использовать небольшое количество итераций или даже одну). Это полезно, если у вас есть только один «мастер-пароль», используемый и для шифрования, и для аутентификации.

Хранение и управление ключами

Самое лучшее — это использовать отдельное специализированное устройство для хранения ключей (HSM).

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

Сжатие данных

В общем случае не стоит сжимать исходный текст до шифрования. Это может дать противнику дополнительный инструмент для анализа.

Например, если вы храните данные сессии в зашифрованных cookie, при этом некоторые из этих данных предоставлены пользователем, а некоторые представляют секретную информацию, противник может узнать дополнительную информацию о секрете, посылая как рядовой пользователь определенным образом сформированные данные и измеряя как меняется длина получаемых шифротекстов.

Текст сжимается более эффективно, если есть повторяющиеся участки. Манипулируя данными пользователя, можно подбирать так, чтоб они частично совпадали с секретными данными. Чем больше совпадение, тем меньший размер шифротекста будет на выходе. Такой тип атаки называется CRIME.

Если у вас нет жесткой необходимости сжимать данные, не сжимайте.

Серверное окружение

Как правило, не стоит размещать требовательные к безопасности приложения на разделяемом сервере. Например, на виртуальном хостинге, где противник может получить доступ к виртуалке на том же физическом сервере, что и вы.

Консультация эксперта

И последнее, но не по важности, проконсультируйтесь с экспертом, пусть он сделает ревью вашего кода, отвечающего за безопасность.

@plo @veorq Я работаю в криптографии с 1997 года, и до сих пор все мои решения и реализации проходят ревью третьей стороной.

Криптографически стойкие случайные числа

Используйте источник случайноси предоставляемый ОС. В PHP, например, mcrypt_create_iv($count, MCRYPT_DEV_URANDOM) или напрямую читайте из /dev/urandom.

Задача надежного шифрования текстовой информации часто встречается при программировании сайтов. В зашифрованном виде бывает необходимо хранить не только пароли, но и другую информацию. Недавно такая задача встала и у меня. Мне нужна была более-менее надежная функция обратимого шифрования текста по ключу. Почему по ключу? Дело в том, что шифрация без ключа может быть взломана, т.к. большинство алгоритмов шифрования можно найти в интернете и подобрать способ, чтобы получить исходные данные, а шифрация с ключом гораздо более надежная.

Обратимое шифрование на PHP 5 библиотекой MCrypt

Поискав по интернету я нашел целых 2 достаточно коротких в плане количества кода и в тоже время очень надежных способа обратимого шифрования по ключу, которые использует встроенную в php библиотеку Mcrypt.

На подавляющем большинстве хостингов данная библиотека сразу же идет вместе с php. Но если вы администрируете свой сервер и данной библиотеки почему-то вдруг не оказалось в составе php, вы всегда можете ее доустановить командой apt-get install php5-mcrypt для Debian-подобных систем (в т.ч. Mint, Ubuntu) или yum install php-mcrypt для RedHat-подобных систем (в т.ч. Fedora, openSUSE, CentOS) или любым другим способом, который вам нравится (через dpkg, rpm, yast и т.д.).

Затем в папке /etc находите папку php, содержащую ini-файлы расширений, загружаемых php по-умолчанию. Посмотреть путь до этой папки можно в php.ini в разделе "Dynamic Extensions". Это может быть папка /etc/php или /etc/php5/mods-available/ или как у меня на сервере /etc/php.d (вообщем, зависит от настроек php). В этой папке должен присутствовать файл mcrypt.ini. Если его там нет, тогда создайте его с таким содержимым:

; Enable mcrypt extension module
extension=mcrypt.so

Итак, теперь приведу примеры 2-х способов шифрования по ключу, которые я нашел для себя в интернете.

1-й способ. Обратимое шифрование по произвольному ключу.

2-й способ. Очень надежное обратимое шифрование по шестандцатиричному ключу.

Внимание! Ключ должен быть шестандцатиричным (символы 0123456789ABCDEF) длиной 32 или 64 символа.

Обратимое шифрование на PHP 7 библиотекой OpenSSL

Функции библиотеки Mcrypt, такие как mcrypt_encrypt и mcrypt_decrypt считаются устаревшими и не рекомендуют их использовать. Начиная с PHP 7.2 библиотеку Mcrypt перенесли в PECL. Вместо MCrypt предлагается использовать openssl_encrypt и openssl_decrypt из библиотеки OpenSSL.

Если всё же хотите подключить MCrypt в PHP 7.2 или выше, чтобы использовать ее функции шифрования, тогда можете посмотреть эту статью.

Обратите внимание : этот алгоритм будет работать начиная с PHP 5.6 и выше. На предыдущих версиях будет выдавать ошибку из-за функции hash_equals, которая осуществляет сравнение строк нечувствительное к атакам по времени (подробнее про атаки по времени можете почитать на википедии).

Другими альтернативами для шифрования на PHP 7+ являются библиотеки: Libsodium и defuse/php-encryption.

Книги по теме:






Посмотреть все книги по программированию

Комментарии к статье:

03.10.17 Павел Спасибо, полезный алгоритм)
02.11.17 Гость Спасибо. Еще вопросик. Как возможно наиболее коротко упаковать значение текущей даты-времени (в формате YmdHisu, т.е. год,месяц. миллисекунды) в короткую символьную строку (цифры и буквы)? В base64 увы, длинновато. И если это возможно, стандартными средствами php 5.4, без доп.расширений вроде GMP и т.п.
03.11.17 Гость GMP функции разрешены на 99% хостингах. Но если все-таки пользоваться только стандартными функциями и больше ничем - значит, придумывать какой-то свой алгоритм или поискать и реализовать готовые алгоритмы, например, алгоритм Хаффмана.
21.05.18 Андрей Например, 21 May 2018 г. 08:45:47 543мс:
Это timestamp: 1526892347543.
А переведя в 36-ричную систему (0. 9A. Z) получим JHG0A3KN (8символов!)
Этого достаточно?
Пишите - phonetoyou [гав] gmail [дот] com.
21.05.18 Андрей можно сократить до 6 (шести) !! если использовать 128ричную систему "0123456789aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZаАбБвВгГдДеЕёЁжЖзЗиИйЙкКлЛмМнНоОпПрРсСтТуУфФхХцЦчЧшШщЩъЪыЫьЬэЭюЮяЯ".
Вот функции:
24.05.18 Гость Пример хороший. Особенно понравилась глобальная переменная.
01.09.18 Гость круто
23.11.18 Гость Могу ли я положить место параметра $_POST запрос ?
07.12.18 Гость Гость, в функцию $_POST, $_GET, $_REQUEST и другие глобальные переменные никто пишет. Передавай аргументов в функцию, а лучше почитай документацию по рнр, если не знаешь как написать функцию.
08.12.18 Гость "Пример хороший. Особенно понравилась глобальная переменная. " школьник, ты придурок. Во-первых тут нет глобальных переменных, во-вторых ты не сможешь объяснить чем плохи глобальные переменные, ну и в третьих ты будешь лохом по жизни, так как пытаешься самоутверждаться как лох.
17.01.19 Тали Не совсем поняла, можно ли его считать симметричным шифрованием?
17.01.19 Гость Да. Раз для шифрования и расшифрования применяется один и тот же ключ - это симметричное шифрование.
06.11.19 Андрей Что это за шифрование такое, если оно заранее допускает миллионы коллизий.
24.12.19 Гость Большое спасибо
18.01.20 Гость спасибо
18.05.20 Richik Какова вероятность получения коллизии шифров? И почему при одном и том-же ключе и при обновлении страницы результаты постоянны разные?
Тестирую 2-й способ-
G2Vl2oaGyFsjUUrQrgmWrjlDBz8nlvdZN6P+QkSDsiqYhgzHkL00uaeykTZuoIKKYlZ8fyi6WtZbsmloYtG8zSgUfFFNKCIAsa+VPxVirLKYkoC8jvp0XmZRxeX3RpX5|n9wMKxLvXjemHenDv7tiHWRj7J8LXmuhN0Ca8y29JUk= - 173 - символов
1234567890 - 10 - символов

yVrP+YSO/01lT0WzimR+TGLnv/J1o+qNIKnUZXWi1fm9P5/RzaR1PrPK2DF1UWxYQ69iX12P1O+4sRCbhAhiSrp3PKeg5sfYHqE4Bxt/ZP4zu9z9zQpgP8SPAxpVbcNT|G2ix5UFmlTnKPtRI85gmB9Vid4ya1aTzWSJbVEidsyM= - 173 - символов
1234567890 - 10 - символов

Как можно закодировать часть PHP кода, так чтобы сайт работал только на том домене который указан в коде, а на другом домене не работал. Какие варианты существуют для решения данного вопроса.

47k 11 11 золотых знаков 74 74 серебряных знака 143 143 бронзовых знака 1,675 2 2 золотых знака 20 20 серебряных знаков 44 44 бронзовых знака
  1. Заложить проверку домена в ядро самого приложения. весь код или только само ядро.

Но те кто захотят украсть ваш код, в любом случае смогут это сделать с помощью деобфускации PHP кода. Как не крути – 100% гарантии нет.

Еще ссылки по теме:


5,836 1 1 золотой знак 13 13 серебряных знаков 35 35 бронзовых знаков

Если код работает на сервере под контролем «злодеев», любую техническую защиту можно обойти. Вопрос времени и стоимости. Сможете сделать это настолько сложным, что ломать (и перепродавать?) дороже, чем купить – вы победили.

Вариант – держать код у себя. Пусть их сайт работает с вашего сервера. Вы будете «заниматься поддержкой и обновлением» и пр. а они вам регулярно (!) платить за хостинг и апдейты.

Можно сделать небольшие закладки в код, которые будут случайно, очень редко, маяковать вашему серверу – так вы узнаете, где ваш код работает – домен, IP. Или заранее позаботьтесь о каких-то уникальных сигнатурах, видимых на сайте извне, и индексируемых поисковиками – чтобы вы могли найти все инсталляции вашего кода через Яндекс/Google.

Подумайте о юридическиской защите. В некоторых странах она совсем не работает, в некоторых (напр. Германии) – вполне, и приносит всем - от владельцев права до юристов, занимающихся вопросом, ощутимую прибыль.

Наконец, поступите нетривиально – выложите ваш код в открытый доступ. А деньги берите за премиум возможности и поддержку.

Непосредственно по теме вопроса. Отличная школа – изучение чужого кода. Скачайте коммерческие продукты на php – темы/плагины WordPress, компоненты Joomla и т.п. и посмотрите, как в них реализована защита – напр. запись о копирайте, назойливо вылезающая на всех страницах, или отключение через месяц пробного периода. «Изучить» значит взломать, докопавшись до сути защиты. Встречаются забавные реализации обфускации кода, замены похожих символов в названиях переменых, методов, констант: COPY_CHECK vs. C0PY_СHECK , base64 кодирование и пр.

Читайте также: