- Обратимое шифрование по ключу на PHP
- Обратимое шифрование на PHP 5 библиотекой MCrypt
- 1-й способ. Обратимое шифрование по произвольному ключу.
- 2-й способ. Очень надежное обратимое шифрование по шестандцатиричному ключу.
- Обратимое шифрование на PHP 7 библиотекой OpenSSL
- base64_decode
- Список параметров
- Возвращаемые значения
- Примеры
- Смотрите также
- User Contributed Notes 17 notes
- kvasilov48 / base64.php
Обратимое шифрование по ключу на PHP
Задача надежного шифрования текстовой информации часто встречается при программировании сайтов. В зашифрованном виде бывает необходимо хранить не только пароли, но и другую информацию. Недавно такая задача встала и у меня. Мне нужна была более-менее надежная функция обратимого шифрования текста по ключу. Почему по ключу? Дело в том, что шифрация без ключа может быть взломана, т.к. большинство алгоритмов шифрования можно найти в интернете и подобрать способ, чтобы получить исходные данные, а шифрация с ключом гораздо более надежная.
Обратимое шифрование на 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
После этого можно включить расширение командой php5enmod mcrypt, а затем перезапустить сервер /etc/init.d/apache2 restart для Debian-систем или service httpd restart для RedHat систем. Разумеется, все описанные действия выполняются с правами root-а.
Итак, теперь приведу примеры 2-х способов шифрования по ключу, которые я нашел для себя в интернете.
1-й способ. Обратимое шифрование по произвольному ключу.
define(‘ENCRYPTION_KEY’, ‘_91X:s+
2-й способ. Очень надежное обратимое шифрование по шестандцатиричному ключу.
Внимание! Ключ должен быть шестандцатиричным (символы 0123456789ABCDEF) длиной 32 или 64 символа.
define('ENCRYPTION_KEY', 'e3f080b6edfcf6fff70654021c7c2e43'); $txt = 'Тестируем обратимое шифрование на php'; $encrypted = mc_encrypt($txt, ENCRYPTION_KEY); echo $encrypted.'
'; $decrypted = mc_decrypt($encrypted, ENCRYPTION_KEY); echo $decrypted; // Encrypt Function function mc_encrypt($encrypt, $key) < $encrypt = serialize($encrypt); $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_DEV_URANDOM); $key = pack('H*', $key); $mac = hash_hmac('sha256', $encrypt, substr(bin2hex($key), -32)); $passcrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $encrypt.$mac, MCRYPT_MODE_CBC, $iv); $encoded = base64_encode($passcrypt).'|'.base64_encode($iv); return $encoded; >// Decrypt Function function mc_decrypt($decrypt, $key) < $decrypt = explode('|', $decrypt.'|'); $decoded = base64_decode($decrypt[0]); $iv = base64_decode($decrypt[1]); if(strlen($iv)!==mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC))< return false; >$key = pack('H*', $key); $decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $decoded, MCRYPT_MODE_CBC, $iv)); $mac = substr($decrypted, -64); $decrypted = substr($decrypted, 0, -64); $calcmac = hash_hmac('sha256', $decrypted, substr(bin2hex($key), -32)); if($calcmac!==$mac) < return false; >$decrypted = unserialize($decrypted); return $decrypted; >
Примечательно, что если выполнить приведенные мной примеры несколько раз, мы увидим каждый раз разные зашифрованные данные, хотя шифровался один и тот же текст. При этом, хоть и зашифрованные данные выглядят по-разному, результат расшифровки всегда один и тот же — исходный текст. Подробнее почитать про библиотеку шифрования можно на php.net. На ее основе можно придумать и свой, уникальный способ обратимого шифрования.
Обратимое шифрование на PHP 7 библиотекой OpenSSL
Функции библиотеки Mcrypt, такие как mcrypt_encrypt и mcrypt_decrypt считаются устаревшими и не рекомендуют их использовать. Начиная с PHP 7.2 библиотеку Mcrypt перенесли в PECL. Вместо MCrypt предлагается использовать openssl_encrypt и openssl_decrypt из библиотеки OpenSSL.
Если всё же хотите подключить MCrypt в PHP 7.2 или выше, чтобы использовать ее функции шифрования, тогда можете посмотреть эту статью.
Однако, вернемся к библиотеке OpenSSL. Эта библиотека содержит множество различных методов и алгоритмов симметричного и асимметричного шифрования. Пока что приведу один пример шифрования этими функциями, взятый с php.net а в будущем, доработаю статью, добавив еще примеры.
define(‘ENCRYPTION_KEY’, ‘ab86d144e3f080b61c7c2e43’); // Encrypt $plaintext = «Тестируем обратимое шифрование на php 7″; $ivlen = openssl_cipher_iv_length($cipher=»AES-128-CBC»); $iv = openssl_random_pseudo_bytes($ivlen); $ciphertext_raw = openssl_encrypt($plaintext, $cipher, ENCRYPTION_KEY, $options=OPENSSL_RAW_DATA, $iv); $hmac = hash_hmac(‘sha256′, $ciphertext_raw, ENCRYPTION_KEY, $as_binary=true); $ciphertext = base64_encode( $iv.$hmac.$ciphertext_raw ); echo $ciphertext.’
‘; // Decrypt $c = base64_decode($ciphertext); $ivlen = openssl_cipher_iv_length($cipher=»AES-128-CBC»); $iv = substr($c, 0, $ivlen); $hmac = substr($c, $ivlen, $sha2len=32); $ciphertext_raw = substr($c, $ivlen+$sha2len); $plaintext = openssl_decrypt($ciphertext_raw, $cipher, ENCRYPTION_KEY, $options=OPENSSL_RAW_DATA, $iv); $calcmac = hash_hmac(‘sha256’, $ciphertext_raw, ENCRYPTION_KEY, $as_binary=true); if (hash_equals($hmac, $calcmac))
Обратите внимание : этот алгоритм будет работать начиная с PHP 5.6 и выше. На предыдущих версиях будет выдавать ошибку из-за функции hash_equals, которая осуществляет сравнение строк нечувствительное к атакам по времени (подробнее про атаки по времени можете почитать на википедии).
Другими альтернативами для шифрования на PHP 7+ являются библиотеки: Libsodium и defuse/php-encryption.
base64_decode
Декодирует строку string , закодированную при помощи base64.
Список параметров
Если параметр strict задан как true , функция base64_decode() вернёт false в случае, если входные данные содержат символы, не входящие в алфавит base64. В противном случае такие символы будут отброшены.
Возвращаемые значения
Возвращает декодированные данные или false в случае возникновения ошибки. Возвращаемые данные могут быть бинарными.
Примеры
Пример #1 Пример использования base64_decode()
$str = ‘0K3RgtC+INC30LDQutC+0LTQuNGA0L7QstCw0L3QvdCw0Y8g0YHRgtGA0L7QutCw’ ;
echo base64_decode ( $str );
?>?php
Результат выполнения данного примера:
Это закодированная строка
Смотрите также
User Contributed Notes 17 notes
If you want to save data that is derived from a Javascript canvas.toDataURL() function, you have to convert blanks into plusses. If you do not do that, the decoded data is corrupted:
$encodedData = str_replace ( ‘ ‘ , ‘+’ , $encodedData );
$decocedData = base64_decode ( $encodedData );
?>
I had some trouble trying to let base64_decode decode base64-strings longer than ~5k chars.
The base64-decoding function is a homomorphism between modulo 4 and modulo 3-length segmented strings. That motivates a divide and conquer approach: Split the encoded string into substrings counting modulo 4 chars, then decode each substring and concatenate all of them.
$decoded = «» ;
for ( $i = 0 ; $i < ceil ( strlen ( $encoded )/ 256 ); $i ++)
$decoded = $decoded . base64_decode ( substr ( $encoded , $i * 256 , 256 ));
?>
where 256 can be replaced by a sufficiently small modulo 4 natural.
This function supports «base64url» as described in Section 5 of RFC 4648, «Base 64 Encoding with URL and Filename Safe Alphabet»
function base64url_decode ( $base64url )
$base64 = strtr ( $base64url , ‘-_’ , ‘+/’ );
$plainText = base64_decode ( $base64 );
return ( $plainText );
>
?>
Base64 for URL parameters/filenames, that adhere to RFC 4648.
Defaults to dropping the padding on encode since it’s not required for decoding, and keeps the URL free of % encodings.
function base64url_encode ( $data , $pad = null ) $data = str_replace (array( ‘+’ , ‘/’ ), array( ‘-‘ , ‘_’ ), base64_encode ( $data ));
if (! $pad ) $data = rtrim ( $data , ‘=’ );
>
return $data ;
>
function base64url_decode ( $data ) return base64_decode ( str_replace (array( ‘-‘ , ‘_’ ), array( ‘+’ , ‘/’ ), $data ));
>
@morgangalpin att gmail dotty com
A better implementation would be the following regular expression:
Which will also detect the usage of = or == at the end of the string (and only end).
If this regex isn’t following proper RFC guidelines, please comment on it.
A function geared specifically toward this:
function is_base64_encoded ()
if ( preg_match ( ‘%^[a-zA-Z0-9/+]*=$%’ , $data )) return TRUE ;
> else return FALSE ;
>
>;
is_base64_encoded ( «iash21iawhdj98UH3» ); // true
is_base64_encoded ( «#iu3498r» ); // false
is_base64_encoded ( «asiudfh9w=8uihf» ); // false
is_base64_encoded ( «a398UIhnj43f/1!+sadfh3w84hduihhjw= keyword»>); // true
To follow up on Starson’s post, PHP was changed to no longer treat a space as if it were a plus sign in CVS revision 1.43.2.1, which corresponds to PHP 5.1.0. You can see what happened with a diff to branch point 1.43 at:
The CVS log indicates that this change was made to fix bug #34214 (base64_decode() does not properly ignore whitespace).
It would seem from the comment preceding the code which was removed that the treatment of the space as if it were the plus sign was actually intentional at one time:
When Base64 gets POSTed, all pluses are interpreted as spaces.
This line changes them back. It’s not exactly the Base64 spec,
but it is completely compatible with it (the spec says that spaces
are invalid). This will also save many people considerable
headache.
However, RFC 3548 states that characters not in the Base64 alphabet should either be ignored or cause the implementation to reject the encoding and RFC 2045 says they should be ignored. So the original code was unfortunately not fully compatible with the spec or other implementations. It may have also masked problems with code not properly escaping POST variables.
The change took place between 5.0.5 and 5.1.0. Exactly where I don’t know or care.
In short php = 5.1.0’s base64_decode( $string ) will no longer make that assumption. I did not see this noted in the change log.
Please note that, as of this writing, mb_convert_encoding( $string, «UTF-8», «BASE64» ) still behaves as base64_decode( $string ) did in php
I was wondering how to decode attached images within mails. Basically they are mostly JPEG files, so it was obviously to write a function that decodes JPEG images.
I guess the plainest way to do so was the following:
function base64_to_jpeg ( $inputfile , $outputfile ) <
/* read data (binary) */
$ifp = fopen ( $inputfile , «rb» );
$imageData = fread ( $ifp , filesize ( $inputfile ) );
fclose ( $ifp );
/* encode & write data (binary) */
$ifp = fopen ( $outputfile , «wb» );
fwrite ( $ifp , base64_decode ( $imageData ) );
fclose ( $ifp );
/* return output filename */
return( $outputfile );
>
?>
This function decodes the given inputfile (a filename!) and saves it to the given outputfile (a filename as well) and then returns the output filename for further usage (e.g. redirect, imagejpeg() and so on).
I thought that might be helpful.
kvasilov48 / base64.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
$ encrypted = encrypt(» to encrypt string «, » secret key «); | |||||||||||||||||||
echo $ encrypted ; | |||||||||||||||||||
$ decrypted = decrypt( $ encrypted , » secret key «); | |||||||||||||||||||
echo $ decrypted ; | |||||||||||||||||||
function encrypt ( $ string , $ key ) | |||||||||||||||||||
$ result = » ; | |||||||||||||||||||
for( $ i = 0 ; $ i $ char = substr( $ string , $ i , 1 ); | $ keychar = substr( $ key , ( $ i % strlen( $ key ))- 1 , 1 ); | $ char = chr(ord( $ char )+ord( $ keychar )); | $ result .= $ char ; | > | return base64_encode( $ result ); | > | function decrypt ( $ string , $ key ) | $ result = » ; | $ string = base64_decode( $ string ); | for( $ i = 0 ; $ i | $ char = substr( $ string , $ i , 1 ); | $ keychar = substr( $ key , ( $ i % strlen( $ key ))- 1 , 1 ); | $ char = chr(ord( $ char )-ord( $ keychar )); | $ result .= $ char ; | > | return $ result ; | > | ?> | |