Двостороннє шифрування: мені потрібно зберігати паролі, які можна отримати


174

Я створюю додаток, який зберігатиме паролі, які користувач може отримати та переглянути. Паролі призначені для апаратного пристрою, тому перевіряти хеші не можна.

Що я повинен знати:

  1. Як зашифрувати та розшифрувати пароль у PHP?

  2. Який найбезпечніший алгоритм для шифрування паролів?

  3. Де я зберігаю приватний ключ?

  4. Замість того, щоб зберігати приватний ключ, чи корисно вимагати від користувачів введення приватного ключа в будь-який час, коли їм знадобиться розшифрований пароль? (Користувачам цієї програми можна довіряти)

  5. Якими способами можна вкрасти та розшифрувати пароль? Що мені потрібно знати?


1
Примітка: Libsodium тепер компілюється в ядро ​​PHP для> = 7.2. Це було б рішенням "перейти до" зараз, оскільки воно повно сучасних методів на відміну від mcrypt, який вважається застарілим і був видалений.
стипендіат

Відповіді:


212

Особисто я хотів би використовувати, mcryptяк інші публікації. Але є ще багато що зауважити ...

  1. Як зашифрувати та розшифрувати пароль у PHP?

    Дивіться нижче про сильний клас, який піклується про все для вас:

  2. Який найбезпечніший алгоритм для шифрування паролів?

    найбезпечніший ? будь-хто з них. Найбезпечніший метод, якщо ви збираєтесь шифрувати, - це захист від уразливості розкриття інформації (XSS, віддалене включення тощо). Якщо він виходить, зловмисник може врешті-решт зламати шифрування (жодне шифрування не може бути 100% незворотним без ключа. Як зазначає @NullUserException, це не зовсім вірно. Є деякі схеми шифрування, які неможливо зламати, наприклад OneTimePad ) .

  3. Де я зберігаю приватний ключ?

    Що я б робив - це використовувати 3 клавіші. Один постачається користувачем, один - специфічним для додатка, а другий - конкретним для користувача (як сіль). Спеціальний ключ програми може зберігатися в будь-якому місці (у конфігураційному файлі за межами веб-кореня, у змінній навколишнього середовища тощо). Спеціальна для користувача інформація зберігатиметься у стовпці в db поруч із зашифрованим паролем. Користувач, який надав, не зберігатиметься. Потім ви зробите щось подібне:

    $key = $userKey . $serverKey . $userSuppliedKey;

    Перевага полягає в тому, що будь-яка 2 клавіші може бути порушена без даних. Якщо є атака SQL Injection, вони можуть отримати $userKeyіншу, але не іншу 2. Якщо існує локальний сервер, вони можуть отримати $userKeyі $serverKey, але не третій $userSuppliedKey. Якщо вони переможуть користувача гайковим ключем, вони можуть дістати $userSuppliedKey, але не інші 2 (але знову ж таки, якщо користувача бити гайковим ключем, ви все одно запізнилися).

  4. Замість того, щоб зберігати приватний ключ, чи корисно вимагати від користувачів введення приватного ключа в будь-який час, коли їм знадобиться розшифрований пароль? (Користувачам цієї програми можна довіряти)

    Абсолютно. Насправді, це єдиний спосіб, як я це зробив би. В іншому випадку вам потрібно буде зберігати незашифровану версію в довговічному форматі зберігання (спільна пам'ять, наприклад, APC або запам’ятована або у файлі сеансу). Це піддається додатковим компромісам. Ніколи не зберігайте незашифровану версію пароля ні в чому, крім локальної змінної.

  5. Якими способами можна вкрасти та розшифрувати пароль? Що мені потрібно знати?

    Будь-яка форма компромісу ваших систем дозволить їм переглядати зашифровані дані. Якщо вони можуть ввести код або потрапити у вашу файлову систему, вони можуть переглядати розшифровані дані (оскільки вони можуть редагувати файли, які дешифрують дані). Будь-яка форма відтворення або атаки MITM також надасть їм повний доступ до залучених ключів. Знюхання необмеженого трафіку HTTP також надасть їм ключі.

    Використовуйте SSL для всього трафіку. І переконайтеся, що на сервері нічого не має вразливих ситуацій (CSRF, XSS, SQL Injection, Privilege Escalation, віддалене виконання коду тощо).

Редагувати: Ось реалізація сильного методу шифрування класом PHP:

/**
 * A class to handle secure encryption and decryption of arbitrary data
 *
 * Note that this is not just straight encryption.  It also has a few other
 *  features in it to make the encrypted data far more secure.  Note that any
 *  other implementations used to decrypt data will have to do the same exact
 *  operations.  
 *
 * Security Benefits:
 *
 * - Uses Key stretching
 * - Hides the Initialization Vector
 * - Does HMAC verification of source data
 *
 */
class Encryption {

    /**
     * @var string $cipher The mcrypt cipher to use for this instance
     */
    protected $cipher = '';

    /**
     * @var int $mode The mcrypt cipher mode to use
     */
    protected $mode = '';

    /**
     * @var int $rounds The number of rounds to feed into PBKDF2 for key generation
     */
    protected $rounds = 100;

    /**
     * Constructor!
     *
     * @param string $cipher The MCRYPT_* cypher to use for this instance
     * @param int    $mode   The MCRYPT_MODE_* mode to use for this instance
     * @param int    $rounds The number of PBKDF2 rounds to do on the key
     */
    public function __construct($cipher, $mode, $rounds = 100) {
        $this->cipher = $cipher;
        $this->mode = $mode;
        $this->rounds = (int) $rounds;
    }

    /**
     * Decrypt the data with the provided key
     *
     * @param string $data The encrypted datat to decrypt
     * @param string $key  The key to use for decryption
     * 
     * @returns string|false The returned string if decryption is successful
     *                           false if it is not
     */
    public function decrypt($data, $key) {
        $salt = substr($data, 0, 128);
        $enc = substr($data, 128, -64);
        $mac = substr($data, -64);

        list ($cipherKey, $macKey, $iv) = $this->getKeys($salt, $key);

        if (!hash_equals(hash_hmac('sha512', $enc, $macKey, true), $mac)) {
             return false;
        }

        $dec = mcrypt_decrypt($this->cipher, $cipherKey, $enc, $this->mode, $iv);

        $data = $this->unpad($dec);

        return $data;
    }

    /**
     * Encrypt the supplied data using the supplied key
     * 
     * @param string $data The data to encrypt
     * @param string $key  The key to encrypt with
     *
     * @returns string The encrypted data
     */
    public function encrypt($data, $key) {
        $salt = mcrypt_create_iv(128, MCRYPT_DEV_URANDOM);
        list ($cipherKey, $macKey, $iv) = $this->getKeys($salt, $key);

        $data = $this->pad($data);

        $enc = mcrypt_encrypt($this->cipher, $cipherKey, $data, $this->mode, $iv);

        $mac = hash_hmac('sha512', $enc, $macKey, true);
        return $salt . $enc . $mac;
    }

    /**
     * Generates a set of keys given a random salt and a master key
     *
     * @param string $salt A random string to change the keys each encryption
     * @param string $key  The supplied key to encrypt with
     *
     * @returns array An array of keys (a cipher key, a mac key, and a IV)
     */
    protected function getKeys($salt, $key) {
        $ivSize = mcrypt_get_iv_size($this->cipher, $this->mode);
        $keySize = mcrypt_get_key_size($this->cipher, $this->mode);
        $length = 2 * $keySize + $ivSize;

        $key = $this->pbkdf2('sha512', $key, $salt, $this->rounds, $length);

        $cipherKey = substr($key, 0, $keySize);
        $macKey = substr($key, $keySize, $keySize);
        $iv = substr($key, 2 * $keySize);
        return array($cipherKey, $macKey, $iv);
    }

    /**
     * Stretch the key using the PBKDF2 algorithm
     *
     * @see http://en.wikipedia.org/wiki/PBKDF2
     *
     * @param string $algo   The algorithm to use
     * @param string $key    The key to stretch
     * @param string $salt   A random salt
     * @param int    $rounds The number of rounds to derive
     * @param int    $length The length of the output key
     *
     * @returns string The derived key.
     */
    protected function pbkdf2($algo, $key, $salt, $rounds, $length) {
        $size   = strlen(hash($algo, '', true));
        $len    = ceil($length / $size);
        $result = '';
        for ($i = 1; $i <= $len; $i++) {
            $tmp = hash_hmac($algo, $salt . pack('N', $i), $key, true);
            $res = $tmp;
            for ($j = 1; $j < $rounds; $j++) {
                 $tmp  = hash_hmac($algo, $tmp, $key, true);
                 $res ^= $tmp;
            }
            $result .= $res;
        }
        return substr($result, 0, $length);
    }

    protected function pad($data) {
        $length = mcrypt_get_block_size($this->cipher, $this->mode);
        $padAmount = $length - strlen($data) % $length;
        if ($padAmount == 0) {
            $padAmount = $length;
        }
        return $data . str_repeat(chr($padAmount), $padAmount);
    }

    protected function unpad($data) {
        $length = mcrypt_get_block_size($this->cipher, $this->mode);
        $last = ord($data[strlen($data) - 1]);
        if ($last > $length) return false;
        if (substr($data, -1 * $last) !== str_repeat(chr($last), $last)) {
            return false;
        }
        return substr($data, 0, -1 * $last);
    }
}

Зверніть увагу , що я використовую функцію додана в PHP 5.6: hash_equals. Якщо у вас менше 5,6, ви можете використовувати цю функцію замінника, яка реалізує безпечну для порівняння функцію порівняння за допомогою подвійної перевірки HMAC :

function hash_equals($a, $b) {
    $key = mcrypt_create_iv(128, MCRYPT_DEV_URANDOM);
    return hash_hmac('sha512', $a, $key) === hash_hmac('sha512', $b, $key);
}

Використання:

$e = new Encryption(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC);
$encryptedData = $e->encrypt($data, $key);

Потім, щоб розшифрувати:

$e2 = new Encryption(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC);
$data = $e2->decrypt($encryptedData, $key);

Зауважте, що я використав $e2другий раз, щоб показати вам, що різні екземпляри все одно належним чином розшифрують дані.

Тепер, як це працює / навіщо використовувати його над іншим рішенням:

  1. Ключі

    • Клавіші не використовуються безпосередньо. Натомість ключ розтягується стандартною деривацією PBKDF2.

    • Ключ, який використовується для шифрування, унікальний для кожного зашифрованого блоку тексту. Отже, наданий ключ стає "головним ключем". Таким чином, цей клас забезпечує обертання клавіш для шифрів та ключів аутентифікації.

    • ВАЖЛИВО ПРИМІТКА , $roundsпараметр налаштований на справжні випадкові ключі достатньої сили (як мінімум 128 біт випадкових криптографічно захищених). Якщо ви збираєтесь використовувати пароль або невипадковий ключ (або менш випадковий, ніж 128 біт випадкового CS), потрібно збільшити цей параметр. Я б запропонував мінімум 10000 для паролів (чим більше ви можете собі дозволити, тим краще, але це додасть часу виконання) ...

  2. Цілісність даних

    • В оновленій версії використовується ENCRYPT-THEN-MAC, що є набагато кращим методом забезпечення достовірності зашифрованих даних.
  3. Шифрування:

    • Він використовує mcrypt для фактичного виконання шифрування. Я б запропонував використовувати або MCRYPT_BLOWFISHабо MCRYPT_RIJNDAEL_128cyphers, і MCRYPT_MODE_CBCдля режиму. Він досить сильний і все ще досить швидкий (цикл шифрування та дешифрування займає на моїй машині приблизно 1/2 секунди).

Тепер, що стосується пункту 3 з першого списку, то, що це дасть вам, є така функція:

function makeKey($userKey, $serverKey, $userSuppliedKey) {
    $key = hash_hmac('sha512', $userKey, $serverKey);
    $key = hash_hmac('sha512', $key, $userSuppliedKey);
    return $key;
}

Ви можете розтягнути її у makeKey()функції, але оскільки вона буде розтягнута пізніше, насправді немає величезного сенсу робити це.

Що стосується розміру пам’яті, він залежить від простого тексту. Blowfish використовує 8-байтний розмір блоку, тож у вас буде:

  • 16 байт для солі
  • 64 байти для hmac
  • довжина даних
  • Прокладка так, що довжина даних% 8 == 0

Отже, для 16-символьного джерела даних шифрується 16 символів даних. Таким чином, це означає, що фактичний розмір зашифрованих даних становить 16 байт за рахунок прокладки. Потім додайте 16 байт для солі та 64 байт для hmac, а загальний збережений розмір - 96 байт. Таким чином, у кращому випадку накладні 80 символів, а в гіршому 87-х символьних накладних ...

Я сподіваюся, що це допоможе ...

Примітка: 12.11.12: Я щойно оновив цей клас МНОГО кращим методом шифрування, використовуючи краще виведені ключі та виправляючи генерацію MAC ...


3
Хтось не розуміє, що це означає "зламати". @IRC приємна робота на уроці, це досить проклятий приємний код.
jcolebrand

1
Наступне повертає помилку. Будь-яка ідея чому? $ x = нове шифрування (MCRYPT_BlOWFISH, MCRYPT_MODE_CBC); $ test = $ x-> шифрування ("тест", "а"); echo var_dump ($ x-> розшифрувати ($ test, "a"));
Довжина хвилі

2
О, і знову в функції розшифровки змінивши два -64s на -128допомогу (так ви отримаєте $enc = substr($data, 128, -128)і$mac = substr($data, -128);
косморогери

4
@ircmaxell Минуло чимало часу з моменту останнього перегляду коду, тому мені цікаво, чи актуальний він. Мені потрібно використовувати щось подібне для фінансової заявки, і було б непогано, якби ви дали добре з цим класом :-)
nt.bas

2
Увага! Розширення mcrypt вже майже десятиліття залишається програмним забезпеченням, і воно також було досить складним у використанні. Таким чином, він застарів на користь OpenSSL, де він буде вилучений з ядра та в PECL в PHP 7.2. th1.php.net/manual/en/migration71.deprecated.php
vee

15

Як зашифрувати та розшифрувати пароль у PHP? Реалізуючи один із багатьох алгоритмів шифрування. (або за допомогою однієї з багатьох бібліотек)

Який найбезпечніший алгоритм для шифрування паролів? Існує багато різних алгоритмів, жоден з яких не на 100% захищений. Але багато з них досить безпечні для комерційних і навіть військових цілей

Де я зберігаю приватний ключ? Якщо ви вирішили застосувати відкритий ключ - алгоритм криптографії (наприклад, RSA), ви не зберігаєте приватний ключ. користувач має приватний ключ. у вашій системі є відкритий ключ, який можна зберігати в будь-якому місці.

Замість того, щоб зберігати приватний ключ, чи корисно вимагати від користувачів введення приватного ключа в будь-який час, коли їм знадобиться розшифрований пароль? (Користувачам цієї програми можна довіряти) Добре, якщо ваш користувач може запам'ятати смішно довгі прості номери - так, чому ні. Але загалом вам потрібно буде придумати систему, яка дозволить користувачеві десь зберігати свій ключ.

Якими способами можна вкрасти та розшифрувати пароль? Що мені потрібно знати? Це залежить від використовуваного алгоритму. Однак завжди переконайтеся, що ви не надсилаєте користувача незашифрований пароль користувачеві або від нього. Або шифруйте / розшифруйте його на стороні клієнта, або використовуйте https (або інші криптографічні засоби для захисту зв'язку між сервером і клієнтом).

Однак якщо вам потрібно всього лише зберігати паролі в зашифрованому вигляді, я б запропонував вам скористатися простим шифром XOR. Основна проблема цього алгоритму полягає в тому, що його можна легко зламати за допомогою частотного аналізу. Однак, як правило, паролі не створюються з довгих абзаців англійського тексту, я не думаю, що вам слід про це турбуватися. Друга проблема XOR Cipher полягає в тому, що якщо у вас є повідомлення в зашифрованій та розшифрованій формі, ви зможете легко дізнатися пароль, за допомогою якого він був зашифрований. Знову ж таки, це не велика проблема у вашому випадку, оскільки вона впливає лише на користувача, який вже був підданий компрометації іншими способами.


У відповіді 3, коли ви говорите, що користувачі мають приватний ключ, я не розумію, що це означає. Ви не рекомендуєте вводити приватні ключі в програму вручну користувачем, то як інакше приватні ключі передаються програмі?
HyderA

Ну, це трохи проблема. Приватний ключ можна зберегти у текстовому файлі, а потім скопіювати його в додаток. Ключ також може бути збережений на сервері, але в цьому випадку він все ще повинен бути зашифрований за допомогою іншого алгоритму шифрування, наприклад XOR. Використання XOR тут у цьому випадку достатньо безпечно, оскільки існує лише одна пара паролів-повідомлень, а повідомлення є досить випадковим, тому аналіз частоти холодним не застосовується.
Іван

4
Я, звичайно, не рекомендую самостійно впроваджувати алгоритм шифрування, надто багато потенційних підводних каменів, а існуючі бібліотеки були перевірені та проаналізовані багатьма людьми.
Довгі вуха

Основна проблема XOR полягає в тому, що якщо хтось вкраде дані вашої програми та знає лише один із паролів користувача, він може розшифрувати всі інші паролі для цього користувача.
Довгі вуха

1
@Ivan: так, але це один із випадків, коли я вважаю, що сам зробив дійсно погано, якщо ви дійсно не розумієте криптографію. Є сильні шифри, які існують, чому б не використовувати їх?
ircmaxell

13
  1. Функція PHP, яку ви переслідуєте, - це Mcrypt ( http://www.php.net/manual/en/intro.mcrypt.php ).

Приклад з посібника трохи відредагований для цього прикладу):

<?php
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = "This is a very secret key";
$pass = "PasswordHere";
echo strlen($pass) . "\n";

$crypttext = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $pass, MCRYPT_MODE_ECB, $iv);
echo strlen($crypttext) . "\n";
?>

Ви будете використовувати mcrypt_decrypt, щоб розшифрувати свій пароль.

  1. Найкращий алгоритм досить суб’єктивний - запитайте 5 людей, отримайте 5 відповідей. Особисто, якщо за замовчуванням (Blowfish) недостатньо для вас, напевно, у вас є більші проблеми!

  2. Зважаючи на те, що PHP потрібен для шифрування - не впевнений, що ви можете його заховати де завгодно - вітайте коментарі з цього приводу. Звичайно, застосовуються стандартні методи кодування PHP.

  3. Враховуючи, що ключ шифрування все одно буде у вашому коді, не впевнений, що ви отримаєте, якщо решта вашої програми буде захищена.

  4. Очевидно, якщо зашифрований пароль і ключ шифрування вкрадені, то гра закінчена.

Я поставив би мотоцикліст на свою відповідь - я не експерт з криптовалют PHP, але, я думаю, те, що я відповів, є стандартною практикою - я вітаю коментарі, які можуть мати інші.


$pass = $text. Я думаю, що він змінив це, щоб задовольнити це питання, і не помітив другого явища.
HyderA

3
Дві речі, що слід зазначити. По-перше, MCRYPT_MODE_ECBне використовується IV. По-друге, якби це було, вам потрібно буде зберігати IV, оскільки без нього ви не можете розшифрувати дані ...
ircmaxell

"Найкращий алгоритм є досить суб'єктивним - запитайте 5 людей, отримайте 5 відповідей. Особисто, якщо за замовчуванням (Blowfish) недостатньо для вас, напевно, у вас є більші проблеми!" Це абсолютно неправильно. Будь-який експерт із криптовалют більше-менш погодиться з gist.github.com/tqbf/be58d2d39690c3b366ad, який спеціально виключає виду
Скотт Арчішевський

6

Багато користувачів пропонують використовувати mcrypt ... це правильно, але мені подобається піти на крок далі, щоб легко зберігатись та передаватись (оскільки іноді зашифровані значення можуть зробити їх важкими для надсилання з використанням інших технологій, таких як curl або json) .

Після того, як ви успішно зашифровані за допомогою mcrypt, запустіть його через base64_encode та перетворіть його в шістнадцятковий код. Отримавши шістнадцятковий код, його легко передати різними способами.

$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
$key = substr("SUPERSECRETKEY",0,mcrypt_enc_get_key_size($td));
mcrypt_generic_init($td, $key, $iv);
$encrypted = mcrypt_generic($td, $unencrypted);
$encrypted = $ua."||||".$iv;
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$encrypted = base64_encode($encrypted);
$encrypted = array_shift(unpack('H*', $encrypted));

А з іншого боку:

$encrypted = pack('H*', $encrypted);
$encrypted = base64_decode($encrypted);
list($encrypted,$iv) = explode("||||",$encrypted,2);
$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$key = substr("SUPERSECRETKEY",0,mcrypt_enc_get_key_size($td));
mcrypt_generic_init($td, $key, $iv);
$unencrypted = mdecrypt_generic($td, $encrypted);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);


2
Ну - це було в 2011 році: П
Бредлі

5

Я б запропонував шифрування відкритим ключем лише у тому випадку, якщо ви хочете, щоб можливість встановити пароль користувача без їх взаємодії (це може бути зручно для скидання та загальних паролів).

Публічний ключ

  1. Розширення OpenSSL , зокрема openssl_public_encryptіopenssl_private_decrypt
  2. Це було б просто RSA, припускаючи, що ваші паролі будуть відповідати розміру ключа - прокладки, інакше вам потрібен симетричний шар
  3. Зберігайте обидва ключі для кожного користувача, парольна фраза приватного ключа - це пароль програми

Симетричний

  1. Mcrypt розширення
  2. AES-256 - це, мабуть, безпечна ставка, але це може бути питанням САМО
  3. Ви цього не зробите - це буде їхній пароль програми

І те й інше

4. Так - користувачам доведеться вводити свій пароль програми щоразу, але зберігання його в сеансі викликає інші проблеми

5.

  • Якщо хтось краде дані програми, він настільки ж безпечний, як симетричний шифр (для схеми відкритого ключа використовується для захисту приватного ключа за допомогою парольної фрази.)
  • Ваша заявка повинна бути доступна лише через SSL, бажано за допомогою клієнтських сертифікатів.
  • Подумайте про додавання другого фактора для аутентифікації, який би використовувався лише один раз на сеанс, як маркер, надісланий через SMS.

Уникайте mcrypt, будьте обережні openssl_private_decrypt().
Скотт Арчішевський

2

Я спробував щось подібне, але зауважте, що я не криптограф і не володію поглибленими знаннями про phpбудь-яку мову програмування. Це просто ідея. Моя ідея полягає в тому, щоб зберігати keyв якомусь файлі або database(або вводити його вручну), який (місцеположення) неможливо легко передбачити (І звичайно, що-небудь буде розшифровано колись, концепція полягає в подовженні часу дешифрування) та шифруванні конфіденційної інформації.

$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH , MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = "evenifyouaccessmydatabaseyouwillneverfindmyemail";
$text = "myemail@domain.com";
echo "Key : ".$key."<br/>";
echo "Text : ".$text . "<br/>";
echo "Md5 : ".md5($text). "<br/>";
echo "Sha1 : ".sha1($text). "<br/>";



$crypttext = mcrypt_encrypt(MCRYPT_BLOWFISH , $key, $text, MCRYPT_MODE_ECB, $iv);
echo "Crypted Data : ".$crypttext."<br>";

$base64 = base64_encode($crypttext);
echo "Encoded Data : ".$base64."<br/>";
$decode =  base64_decode($base64);


$decryptdata = mcrypt_decrypt(MCRYPT_BLOWFISH , $key, $crypttext, MCRYPT_MODE_ECB, $iv);

echo "Decoded Data : ".ereg_replace("?", null ,  $decryptdata); 
//event if i add '?' to the sting to the text it works, I don't know why.

Зверніть увагу, що це лише концепція. Будь-яке вдосконалення цього коду було б дуже помітним.


2

Паролі призначені для апаратного пристрою, тому перевіряти хеші не можна

Так? Я не розумію. Ви просто маєте на увазі, що пароль потрібно відновити?

Як говорили інші, розширення mcrypt забезпечує доступ до безлічі криптографічних функцій - однак ви пропонуєте своїм користувачам покласти всі свої яйця в один кошик - той, який потенційно може бути мішенню для зловмисників - і якщо ви навіть не знаєте як почати вирішувати проблему, тоді ви робите своїм користувачам сумлінну послугу. Ви не в змозі зрозуміти, як захистити дані.

Більшість уразливостей безпеки виникає не тому, що алгоритм, що лежить в основі, є несправним або незахищеним, а через проблеми з використанням алгоритму в коді програми.

Сказавши це, можна побудувати досить безпечну систему.

Вам слід враховувати асиметричне шифрування лише тоді, коли у вас є вимога до користувача створити захищене повідомлення, яке читається іншим (конкретним) користувачем. Причина в тому, що її обчислювально дорого. Якщо ви просто хочете надати сховище для користувачів, щоб вводити та отримувати власні дані, симетричне шифрування є адекватним.

Якщо ви зберігаєте ключ для розшифровки повідомлення там, де зашифроване повідомлення (або там, де зашифроване повідомлення зберігається), система не захищена. Використовуйте той же маркер для автентифікації користувача, що і для ключа розшифровки (або у випадку асиметричного шифрування використовуйте маркер як пропускну фразу приватного ключа). Оскільки вам потрібно буде зберегти маркер на сервері, де відбувається дешифрування принаймні тимчасово, ви можете розглянути можливість використання субстрату для зберігання сеансу, який не можна шукати, або передати маркер безпосередньо демону, пов'язаному з сеансом, який зберігатиме маркувати в пам'яті та виконувати розшифровку повідомлень на вимогу.


1

Використовуйте password_hash та password_verify

<?php
/**
 * In this case, we want to increase the default cost for BCRYPT to 12.
 * Note that we also switched to BCRYPT, which will always be 60 characters.
 */
$options = [
    'cost' => 12,
];
echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $options)."\n";
?>

І розшифрувати:

<?php
// See the password_hash() example to see where this came from.
$hash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';

if (password_verify('rasmuslerdorf', $hash)) {
    echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}
?>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.