Я имею в виду:
Original String + Salt or Key --> Encrypted String Encrypted String + Salt or Key --> Decrypted (Original String)
Может быть, что-то вроде:
"hello world!" + "ABCD1234" --> Encrypt --> "2a2ffa8f13220befbe30819047e23b2c" (may be, for eg) "2a2ffa8f13220befbe30819047e23b2c" --> Decrypt with "ABCD1234" --> "hello world!"
Попытка использовать Crypt_Blowfish
, но это не сработало для меня.
Прежде чем делать что-либо еще, попытайтесь понять разницу между шифрованием и аутентификацией , и почему вы, вероятно, хотите использовать аутентифицированное шифрование, а не просто шифрование .
Чтобы реализовать аутентифицированное шифрование, вы хотите шифровать MAC-адрес. Порядок шифрования и аутентификации очень важен! Один из существующих ответов на этот вопрос допустил эту ошибку; как и многие криптографические библиотеки, написанные на PHP.
Вам следует избегать реализации собственной криптографии и вместо этого использовать защищенную библиотеку, написанную экспертами криптографии и рассмотренную ими.
Используйте libsodium, если у вас есть доступ PECL (или натрия_compat, если вы хотите libsodium без PECL); в противном случае…
Использовать defuse / php-encryption ; не сворачивайте свою собственную криптографию!
Обе библиотеки, связанные выше, облегчают и безболезненно внедрять аутентифицированное шифрование в ваши собственные библиотеки.
Если вы все еще хотите написать и развернуть свою собственную криптографическую библиотеку, против обычной мудрости каждого специалиста по криптографии в Интернете, это шаги, которые вам нужно будет предпринять.
hash_equals()
. Если это не удастся, отмените. mb_strlen()
и mb_substr()
, используя режим набора символов '8bit'
mb_substr()
, чтобы предотвратить проблемы с mbstring.func_overload
. mcrypt_create_iv()
, НЕ ИСПОЛЬЗУЙТЕ MCRYPT_RAND
!
bin2hex()
, base64_encode()
и т. д. могут утечка информации о ваших ключах шифрования через тайник синхронизации. Избегайте их, если это возможно. Даже если вы будете следовать приведенным здесь советам, многие могут ошибиться в криптографии. Всегда проверяйте свою реализацию криптографическим экспертом. Если вам не посчастливилось быть личным другом с учеником-криптографом в вашем местном университете, вы всегда можете попробовать форум Cryptography Stack Exchange для консультаций.
Если вам нужен профессиональный анализ вашей реализации, вы всегда можете нанять авторитетную команду консультантов по безопасности, чтобы просмотреть свой криптографический код PHP (раскрытие: мой работодатель).
Не шифруйте пароли . Вместо этого вы хотите использовать их вместо них, используя один из этих алгоритмов с помощью пароля:
Никогда не используйте универсальную хеш-функцию (MD5, SHA256) для хранения паролей.
Не шифруйте параметры URL . Это неправильный инструмент для работы.
Если у вас нет установленного libsodium, вы можете использовать sodium_compat для достижения того же результата (хотя и медленнее).
<?php // This requires the libsodium PECL extension /** * Encrypt a message * * @param string $message - message to encrypt * @param string $key - encryption key * @return string */ function safeEncrypt($message, $key) { $nonce = \Sodium\randombytes_buf( \Sodium\CRYPTO_SECRETBOX_NONCEBYTES ); $cipher = base64_encode( $nonce. \Sodium\crypto_secretbox( $message, $nonce, $key ) ); \Sodium\memzero($message); \Sodium\memzero($key); return $cipher; } /** * Decrypt a message * * @param string $encrypted - message encrypted with safeEncrypt() * @param string $key - encryption key * @return string */ function safeDecrypt($encrypted, $key) { $decoded = base64_decode($encrypted); $nonce = mb_substr($decoded, 0, \Sodium\CRYPTO_SECRETBOX_NONCEBYTES, '8bit'); $ciphertext = mb_substr($decoded, \Sodium\CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit'); $plain = \Sodium\crypto_secretbox_open( $ciphertext, $nonce, $key ); \Sodium\memzero($ciphertext); \Sodium\memzero($key); return $plain; }
Затем, чтобы проверить это:
<?php // This refers to the previous code block. require "safeCrypto.php"; // Do this once then store it somehow: $key = \Sodium\randombytes_buf( \Sodium\CRYPTO_SECRETBOX_KEYBYTES ); $message = 'We are all living in a yellow submarine'; $ciphertext = safeEncrypt($message, $key); $plaintext = safeDecrypt($ciphertext, $key); var_dump($ciphertext); var_dump($plaintext);
Один из проектов, над которыми я работал, – это библиотека шифрования Halite , цель которой – сделать libsodium проще и интуитивно понятным.
<?php use \ParagonIE\Halite\KeyFactory; use \ParagonIE\Halite\Symmetric\Crypto as SymmetricCrypto; // Generate a new random symmetric-key encryption key. You're going to want to store this: $key = new KeyFactory::generateEncryptionKey(); // To save your encryption key: KeyFactory::save($key, '/path/to/secret.key'); // To load it again: $loadedkey = KeyFactory::loadEncryptionKey('/path/to/secret.key'); $message = 'We are all living in a yellow submarine'; $ciphertext = SymmetricCrypto::encrypt($message, $key); $plaintext = SymmetricCrypto::decrypt($ciphertext, $key); var_dump($ciphertext); var_dump($plaintext);
Все основные криптографии обрабатываются libsodium. Очевидно, это означает, что вам нужно расширение PECL для использования Halite.
<?php /** * This requires https://github.com/defuse/php-encryption * php composer.phar require defuse/php-encryption * * Note that v2.0.0 is around the corner and this might need * to be edited when it's finally released. */ use \Defuse\Crypto\Crypto; require "vendor/autoload.php"; // Do this once then store it somehow: $key = Crypto::createNewRandomKey(); $message = 'We are all living in a yellow submarine'; $ciphertext = Crypto::encrypt($message, $key); $plaintext = Crypto::decrypt($ciphertext, $key); var_dump($ciphertext); var_dump($plaintext);
Примечание . Crypto::encrypt()
возвращает исходный двоичный код, поэтому вы можете использовать base64_encode()
и base64_decode()
для хранения / передачи зашифрованных текстов для предотвращения ошибок кодирования. В версии 2 по умолчанию будет выводиться шестнадцатеричный код.
Если у вас возникает соблазн использовать «пароль», остановитесь прямо сейчас. Вам нужен случайный 128-битный ключ шифрования, а не памятный пароль человека.
Вы можете хранить ключ шифрования для долгосрочного использования так:
$storeMe = bin2hex($key);
И, по требованию, вы можете получить его так:
$key = hex2bin($storeMe);
Я настоятельно рекомендую просто хранить случайно сгенерированный ключ для долгосрочного использования, а не любой пароль в качестве ключа (или для получения ключа).
Это плохая идея, но все в порядке, вот как это сделать безопасно.
Сначала создайте случайный ключ и сохраните его в константе.
/** * Replace this with your own salt! * Use bin2hex() then add \x before every 2 hex characters, like so: */ define('MY_PBKDF2_SALT', "\x2d\xb7\x68\x1a\x28\x15\xbe\x06\x33\xa0\x7e\x0e\x8f\x79\xd5\xdf");
Обратите внимание, что вы добавляете дополнительную работу и можете просто использовать эту константу в качестве ключа и сэкономить себе массу страдания!
Затем используйте PBKDF2 (например, так), чтобы получить подходящий ключ шифрования с вашего пароля, а не шифровать его паролем напрямую.
/** * Get an AES key from a static password and a secret salt * * @param string $password Your weak password here * @param int $keysize Number of bytes in encryption key */ function getKeyFromPassword($password, $keysize = 16) { return hash_pbkdf2( 'sha256', $password, MY_PBKDF2_SALT, 100000, // Number of iterations $keysize, true ); }
Не используйте только 16-символьный пароль. Ваш ключ шифрования будет нарушен.
Чего не делать
ПРЕДУПРЕЖДЕНИЕ:
В этом ответе используется ЕЦБ . ECB не является режимом шифрования, это всего лишь строительный блок. Использование ECB, как показано в этом ответе, фактически не шифрует строку безопасно. Не используйте ECB в своем коде. См . Ответ Скотта для хорошего решения.
Я получил это на себя. На самом деле я нашел ответ на Google и только что изменил что-то. Однако результат совершенно небезопасен.
<?php define("ENCRYPTION_KEY", "!@#$%^&*"); $string = "This is the original data string!"; echo $encrypted = encrypt($string, ENCRYPTION_KEY); echo "<br />"; echo $decrypted = decrypt($encrypted, ENCRYPTION_KEY); /** * Returns an encrypted & utf8-encoded */ function encrypt($pure_string, $encryption_key) { $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB); $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); $encrypted_string = mcrypt_encrypt(MCRYPT_BLOWFISH, $encryption_key, utf8_encode($pure_string), MCRYPT_MODE_ECB, $iv); return $encrypted_string; } /** * Returns decrypted original string */ function decrypt($encrypted_string, $encryption_key) { $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB); $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); $decrypted_string = mcrypt_decrypt(MCRYPT_BLOWFISH, $encryption_key, $encrypted_string, MCRYPT_MODE_ECB, $iv); return $decrypted_string; } ?>
Я опаздываю на вечеринку, но ища правильный способ сделать это. Я наткнулся на эту страницу, и это был один из лучших результатов поиска Google, поэтому я хотел бы поделиться своим взглядом на проблему, которую я считаю на момент написания этого сообщения (начало 2017 года). Из PHP mcrypt_decrypt
и mcrypt_encrypt
будут устаревать, поэтому для построения будущего кода защиты следует использовать openssl_encrypt и openssl_decrypt
Вы можете сделать что-то вроде:
$string_to_encrypt="Test"; $password="password"; $encrypted_string=openssl_encrypt($string_to_encrypt,"AES-128-ECB",$password); $decrypted_string=openssl_decrypt($encrypted_string,"AES-128-ECB",$password);
Важно : для этого используется режим ECB , который не является безопасным. Если вы хотите простое решение, не беря курс критики в криптографической инженерии, не пишите его сами, просто используйте библиотеку .
Вы можете использовать любые другие методы измельчителя, в зависимости от ваших потребностей в безопасности. Чтобы узнать доступные способы измельчения, см. Функцию openssl_get_cipher_methods .
Если вы используете Laravel framework, проще всего зашифровать и расшифровать с помощью внутренних функций.
$string = 'Some text to be encrypted'; $encrypted = \Illuminate\Support\Facades\Crypt::encrypt($string); $decrypted_string = \Illuminate\Support\Facades\Crypt::decrypt($encrypted); var_dump($string); var_dump($encrypted); var_dump($decrypted_string);
Примечание. Обязательно установите случайную строку 16, 24 или 32 символа в ключевой опции файла config / app.php. В противном случае зашифрованные значения не будут защищены.
Историческое примечание: это было написано во время PHP4. Это то, что мы называем теперь «устаревшим кодом».
Я оставил этот ответ в исторических целях, но некоторые из методов теперь устарели, метод шифрования DES не рекомендуется и т. Д.
Я не обновил этот код по двум причинам: 1) я больше не работаю с методами шифрования вручную на PHP, и 2) этот код по-прежнему служит той цели, для которой он предназначен: продемонстрировать минимальную, упрощенную концепцию использования шифрования в PHP.
Если вы найдете аналогично упрощенную версию источника PHP, которая может заставить людей запускаться в 10-20 строк кода или меньше, дайте мне знать в комментариях.
Помимо этого, пожалуйста, наслаждайтесь классическим Эпизодом минималистичного ответа на шифрование PHP4 от ранней эры.
В идеале у вас есть – или вы можете получить доступ к библиотеке PHP mcrypt, так как это, безусловно, популярно и очень полезно для множества задач. Ниже приведен пример использования различных типов шифрования и кода примера: методы шифрования в PHP
//Listing 3: Encrypting Data Using the mcrypt_ecb Function <?php echo("<h3> Symmetric Encryption </h3>"); $key_value = "KEYVALUE"; $plain_text = "PLAINTEXT"; $encrypted_text = mcrypt_ecb(MCRYPT_DES, $key_value, $plain_text, MCRYPT_ENCRYPT); echo ("<p><b> Text after encryption : </b>"); echo ( $encrypted_text ); $decrypted_text = mcrypt_ecb(MCRYPT_DES, $key_value, $encrypted_text, MCRYPT_DECRYPT); echo ("<p><b> Text after decryption : </b>"); echo ( $decrypted_text ); ?>
Несколько предупреждений:
1) Никогда не используйте обратимое или «симметричное» шифрование, когда будет выполняться односторонний хеш.
2) Если данные действительно чувствительны, например, номера кредитной карты или социального обеспечения, остановитесь; вам нужно больше, чем любой простой кусок кода, но вам нужна крипто-библиотека, предназначенная для этой цели, и значительное количество времени для исследования необходимых методов. Кроме того, криптование программного обеспечения, вероятно, составляет <10% от безопасности конфиденциальных данных. Это похоже на переделку атомной электростанции – признайте, что эта задача опасна и сложна и не зная, если это так. Финансовые штрафы могут быть огромными, поэтому лучше использовать услугу и нести ответственность за них.
3) Любое легко реализуемое шифрование, перечисленное здесь, может разумно защитить незначительно важную информацию, которую вы хотите сохранить от посторонних глаз или ограничить воздействие в случае случайной / преднамеренной утечки. Но, видя, как ключ хранится в текстовом виде на веб-сервере, если они могут получить данные, они могут получить ключ дешифрования.
Как бы то ни было, получайте удовольствие 🙂