Как шифровать / расшифровывать данные в php?



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



вот что я пытаюсь сделать:



у меня есть таблица, состоящая из этих полей (UserID, Fname, Lname, Email, Пароль)



Я хочу, чтобы все поля были зашифрованы, а затем расшифрованы(можно ли использовать sha256 для шифрование / расшифровка, если нет алгоритма шифрования)



еще одна вещь, которую я хочу узнать, как создать один путь hash(sha256) в сочетании с хорошим "соль".
(В основном я просто хочу иметь простую реализацию шифрования / дешифрования,hash(sha256)+salt)

Сэр / мэм, ваши ответы будут очень полезны и будут очень оценены. Спасибо++

1901   6  

6 ответов:

предисловие

начиная с определения таблицы:

- UserID
- Fname
- Lname
- Email
- Password
- IV

список изменений:

  1. поля Fname,Lname и Email будет зашифрован с помощью симметричного шифра, предоставленного OpenSSL,
  2. The IV поле будет хранить вектор инициализации используется для шифрования. Требования к хранению зависят от используемого шифра и режима; Подробнее об этом позже.
  3. The Password поле будет хэшироваться с помощью в один конец хэш пароля,

безопасность

шифр и режим

выбор лучшего шифра и Режима Шифрования выходит за рамки этого ответа, но окончательный выбор влияет на размер как ключа шифрования, так и вектора инициализации; для этого сообщения мы будем использовать AES-256-CBC, который имеет фиксированный размер блока 16 байт и размер ключа либо 16, 24 или 32 байта.

ключ шифрования

хороший ключ шифрования-это двоичный blob, который генерируется из надежного генератора случайных чисел. Рекомендуется использовать следующий пример (>= 5.3):

$key_size = 32; // 256 bits
$encryption_key = openssl_random_pseudo_bytes($key_size, $strong);
// $strong will be true if the key is crypto safe

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

IV

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

функция предоставляется, чтобы помочь вам создать IV:

$iv_size = 16; // 128 bits
$iv = openssl_random_pseudo_bytes($iv_size, $strong);

пример

давайте зашифруем поле имя, используя ранее $encryption_key и $iv; для этого мы должны заполнить наши данные до размера блока:

function pkcs7_pad($data, $size)
{
    $length = $size - strlen($data) % $size;
    return $data . str_repeat(chr($length), $length);
}

$name = 'Jack';
$enc_name = openssl_encrypt(
    pkcs7_pad($name, 16), // padded data
    'AES-256-CBC',        // cipher and mode
    $encryption_key,      // secret key
    0,                    // options (not used)
    $iv                   // initialisation vector
);

хранение требования

зашифрованный вывод, как и IV, является двоичным; хранение этих значений в базе данных может быть выполнено с помощью назначенных типов столбцов, таких как BINARY или VARBINARY.

выходное значение, как и IV, является двоичным; чтобы сохранить эти значения в MySQL, рассмотрите возможность использования BINARY или VARBINARY столбцы. Если это не вариант, вы также можете преобразовать двоичные данные в текстовое представление с помощью base64_encode() или bin2hex(), для этого требуется от 33% до 100% больше места для хранения.

дешифрования

расшифровка сохраненных значений аналогична:

function pkcs7_unpad($data)
{
    return substr($data, 0, -ord($data[strlen($data) - 1]));
}

$row = $result->fetch(PDO::FETCH_ASSOC); // read from database result
// $enc_name = base64_decode($row['Name']);
// $enc_name = hex2bin($row['Name']);
$enc_name = $row['Name'];
// $iv = base64_decode($row['IV']);
// $iv = hex2bin($row['IV']);
$iv = $row['IV'];

$name = pkcs7_unpad(openssl_decrypt(
    $enc_name,
    'AES-256-CBC',
    $encryption_key,
    0,
    $iv
));

аутентифицированного шифрования

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

пример

// generate once, keep safe
$auth_key = openssl_random_pseudo_bytes(32, $strong);

// authentication
$auth = hash_hmac('sha256', $enc_name, $auth_key, true);
$auth_enc_name = $auth . $enc_name;

// verification
$auth = substr($auth_enc_name, 0, 32);
$enc_name = substr($auth_enc_name, 32);
$actual_auth = hash_hmac('sha256', $enc_name, $auth_key, true);

if (hash_equals($auth, $actual_auth)) {
    // perform decryption
}

Читайте также: hash_equals()

хеширования

хранение обратимого пароля в базе данных следует избегать как можно больше; вы только хотите проверить пароль, а не знать его содержимое. Если пользователь теряет свой пароль, лучше позволить ему сбросить его, а не отправлять им свой оригинальный (убедитесь, что пароль сброс может быть выполнен только в течение ограниченного времени).

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

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

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

в настоящее время есть два популярных варианта:

  1. PBKDF2 (функция вывода ключа на основе пароля v2)
  2. bcrypt (он же Blowfish)

этот ответ будет использовать пример с bcrypt.

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

$password = 'my password';
$random = openssl_random_pseudo_bytes(18);
$salt = sprintf('y$%02d$%s',
    13, // 2^n cost factor
    substr(strtr(base64_encode($random), '+', '.'), 0, 22)
);

$hash = crypt($password, $salt);

соль генерируется с openssl_random_pseudo_bytes() чтобы сформировать случайный blob данных, которые затем проходят через base64_encode() и strtr() чтобы соответствовать требуемому алфавиту [A-Za-z0-9/.].

The crypt() функция выполняет хэширование на основе алгоритма (y$ для Blowfish), фактор цены (фактор 13 принимает грубо 0.40 s на машине 3GHz) и соль 22 письмена.

проверка

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

$given_password = $_POST['password']; // the submitted password
$db_hash = $row['Password']; // field with the password hash

$given_hash = crypt($given_password, $db_hash);

if (isEqual($given_hash, $db_hash)) {
    // user password verified
}

// constant time string compare
function isEqual($str1, $str2)
{
    $n1 = strlen($str1);
    if (strlen($str2) != $n1) {
        return false;
    }
    for ($i = 0, $diff = 0; $i != $n1; ++$i) {
        $diff |= ord($str1[$i]) ^ ord($str2[$i]);
    }
    return !$diff;
}

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

хэширование паролей в PHP 5.5

PHP 5.5 представил функции хэширования пароля что вы можете использовать для упрощения вышеуказанного метода хэширования:

$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 13]);

и проверки:

if (password_verify($given_password, $db_hash)) {
    // password valid
}

Читайте также: password_hash(),password_verify()

Я думаю, что это был ответ раньше...но в любом случае, если вы хотите зашифровать/расшифровать данные, вы не можете использовать SHA256

//Key
$key = 'SuperSecretKey';

//To Encrypt:
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, 'I want to encrypt this', MCRYPT_MODE_ECB);

//To Decrypt:
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted, MCRYPT_MODE_ECB);

ответ фон и объяснение

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

то, что вы хотите использовать, является двусторонней функцией, но более конкретно,Блочный Шифр. Функция, которая позволяет как для шифрования, так и для расшифровки данных. Функции mcrypt_encrypt и mcrypt_decrypt по умолчанию используйте алгоритм Blowfish. Использование PHP mcrypt можно найти в этом руководство. Список шифр определений для выбора шифра mcrypt использует также существует. Вики на Blowfish можно найти по адресу Википедия. Блочный шифр шифрует входные данные в блоках известного размера и позиции с известным ключом, так что данные могут быть расшифрованы с помощью ключа. Это то, что SHA256 не может предоставить вам.

код

$key = 'ThisIsTheCipherKey';

$ciphertext = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, 'This is plaintext.', MCRYPT_MODE_CFB);

$plaintext = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $encrypted, MCRYPT_MODE_CFB);

вот пример использования openssl_encrypt

//Encryption:
$textToEncrypt = "My Text to Encrypt";
$encryptionMethod = "AES-256-CBC";
$secretHash = "encryptionhash";
$iv = mcrypt_create_iv(16, MCRYPT_RAND);
$encryptedText = openssl_encrypt($textToEncrypt,$encryptionMethod,$secretHash, 0, $iv);

//Decryption:
$decryptedText = openssl_decrypt($encryptedText, $encryptionMethod, $secretHash, 0, $iv);
print "My Decrypted Text: ". $decryptedText;

мне потребовалось довольно много времени, чтобы понять, как не получить false при использовании openssl_decrypt() и получить шифровать и расшифровывать работу.

    // cryptographic key of a binary string 16 bytes long (because AES-128 has a key size of 16 bytes)
    $encryption_key = '58adf8c78efef9570c447295008e2e6e'; // example
    $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
    $encrypted = openssl_encrypt($plaintext, 'aes-256-cbc', $encryption_key, OPENSSL_RAW_DATA, $iv);
    $encrypted = $encrypted . ':' . base64_encode($iv);

    // decrypt to get again $plaintext
    $parts = explode(':', $encrypted);
    $decrypted = openssl_decrypt($parts[0], 'aes-256-cbc', $encryption_key, OPENSSL_RAW_DATA, base64_decode($parts[1])); 

если вы хотите передать зашифрованную строку через URL, вам нужно urlencode строку:

    $encrypted = urlencode($encrypted);

чтобы лучше понять, что происходит, читать:

для генерации ключей длиной 16 байт вы можете использовать:

    $bytes = openssl_random_pseudo_bytes(16);
    $hex = bin2hex($bytes);

для просмотра сообщений об ошибках openssl вы можете использовать:echo openssl_error_string();

надеюсь, что это поможет.

     function my_simple_crypt( $string, $action = 'e' ) {
        // you may change these values to your own
        $secret_key = 'my_simple_secret_key';
        $secret_iv = 'my_simple_secret_iv';

        $output = false;
        $encrypt_method = "AES-256-CBC";
        $key = hash( 'sha256', $secret_key );
        $iv = substr( hash( 'sha256', $secret_iv ), 0, 16 );

        if( $action == 'e' ) {
            $output = base64_encode( openssl_encrypt( $string, $encrypt_method, $key, 0, $iv ) );
        }
        else if( $action == 'd' ){
            $output = openssl_decrypt( base64_decode( $string ), $encrypt_method, $key, 0, $iv );
        }

        return $output;
    }

Comments

    Ничего не найдено.