Я сейчас студент и изучаю PHP, пытаюсь сделать простое шифрование / дешифрование данных на PHP. Я провел несколько онлайн-исследований, и некоторые из них были довольно запутанными (по крайней мере, для меня).
Вот что я пытаюсь сделать:
У меня есть таблица, состоящая из этих полей (UserID, Fname, Lname, Email, Password)
Я хочу, чтобы все поля были зашифрованы, а затем расшифрованы (можно ли использовать sha256
для шифрования / дешифрования, если не какой-либо алгоритм шифрования)
Еще одна вещь, которую я хочу узнать, - это как создать одностороннюю работу в hash(sha256)
сочетании с хорошей «солью». (По сути, я просто хочу иметь простую реализацию шифрования / дешифрования, hash(sha256)+salt)
сэр / мэм, ваши ответы будут очень полезны и будут очень признательны. Спасибо ++
источник
Ответы:
Предисловие
Начиная с определения вашей таблицы:
Вот изменения:
Fname
,Lname
иEmail
будут зашифрованы с помощью симметричного шифра, предоставляемую OpenSSL ,IV
поле будет храниться вектор инициализации, используемый для шифрования. Требования к хранилищу зависят от используемого шифра и режима; подробнее об этом позже.Password
Поле будет хэшируются с использованием одностороннюю хэш пароля,Шифрование
Шифр и режим
Выбор лучшего шифра и режима шифрования выходит за рамки этого ответа, но окончательный выбор влияет на размер как ключа шифрования, так и вектора инициализации; для этого поста мы будем использовать AES-256-CBC, который имеет фиксированный размер блока 16 байтов и размер ключа 16, 24 или 32 байта.
Ключ шифрования
Хороший ключ шифрования - это двоичный большой двоичный объект, который генерируется надежным генератором случайных чисел. Рекомендуется следующий пример (> = 5,3):
Это можно сделать один или несколько раз (если вы хотите создать цепочку ключей шифрования). Держите их как можно конфиденциальнее.
IV
Вектор инициализации добавляет случайности к шифрованию и требуется для режима CBC. Эти значения в идеале должны использоваться только один раз (технически один раз для каждого ключа шифрования), поэтому обновление любой части строки должно восстанавливать ее.
Предоставляется функция, которая поможет вам сгенерировать IV:
пример
Давайте зашифруем поле имени, используя предыдущие
$encryption_key
и$iv
; для этого мы должны дополнить наши данные размером блока:Требования к хранилищу
Зашифрованный вывод, как и IV, является двоичным; сохранение этих значений в базе данных может быть выполнено с использованием определенных типов столбцов, таких как
BINARY
илиVARBINARY
.Выходное значение, как и IV, является двоичным; чтобы сохранить эти значения в MySQL, рассмотрите возможность использования столбцов
BINARY
илиVARBINARY
. Если это не вариант, вы также можете преобразовать двоичные данные в текстовое представление, используяbase64_encode()
илиbin2hex()
, для этого потребуется от 33% до 100% больше места для хранения.Дешифрирование
Расшифровка сохраненных значений аналогична:
Аутентифицированное шифрование
Вы можете дополнительно улучшить целостность сгенерированного зашифрованного текста, добавив подпись, созданную на основе секретного ключа (отличного от ключа шифрования) и зашифрованного текста. Перед расшифровкой зашифрованного текста сначала проверяется подпись (предпочтительно с помощью метода сравнения с постоянным временем).
пример
Смотрите также:
hash_equals()
Хэш
По возможности следует избегать хранения обратимого пароля в вашей базе данных; вы хотите только проверить пароль, а не знать его содержимое. Если пользователь теряет свой пароль, лучше позволить ему сбросить его, а не отправлять им исходный (убедитесь, что сброс пароля может быть выполнен только в течение ограниченного времени).
Применение хеш-функции - это односторонняя операция; впоследствии его можно безопасно использовать для проверки без раскрытия исходных данных; Что касается паролей, то для их обнаружения можно использовать метод грубой силы из-за его относительно короткой длины и плохого выбора пароля многими людьми.
Алгоритмы хеширования, такие как MD5 или SHA1, были созданы для проверки содержимого файла по известному значению хеш-функции. Они значительно оптимизированы, чтобы сделать эту проверку максимально быстрой, но при этом оставаясь точной. Учитывая относительно ограниченное пространство для вывода, было легко создать базу данных с известными паролями и соответствующими выходными хэш-значениями - радужными таблицами.
Добавление соли к паролю перед хешированием сделало бы радужную таблицу бесполезной, но недавние аппаратные достижения сделали поиск методом грубой силы жизнеспособным подходом. Вот почему вам нужен алгоритм хеширования, который заведомо медленный и просто невозможно оптимизировать. Он также должен иметь возможность увеличивать нагрузку на более быстрое оборудование, не влияя на возможность проверки существующих хэшей паролей, чтобы сделать их надежными в будущем.
В настоящее время доступны два популярных варианта:
В этом ответе будет использоваться пример с bcrypt.
поколение
Хеш пароля можно сгенерировать так:
Соль создается с помощью,
openssl_random_pseudo_bytes()
чтобы сформировать случайный блок данных, который затем обрабатываетсяbase64_encode()
иstrtr()
соответствует требуемому алфавиту[A-Za-z0-9/.]
.В
crypt()
функции выполняет хэширование на основе алгоритма ($2y$
для Blowfish), фактор стоимости (коэффициент 13 занимает примерно 0.40s на машине 3GHz) и соли 22 символов.Проверка
После того, как вы выбрали строку, содержащую информацию о пользователе, вы проверяете пароль следующим образом:
Чтобы проверить пароль, вы звоните еще
crypt()
раз, но передаете ранее вычисленный хэш в качестве значения соли. Возвращаемое значение дает тот же хеш, если данный пароль совпадает с хешем. Для проверки хэша часто рекомендуется использовать функцию сравнения с постоянным временем, чтобы избежать временных атак.Хеширование паролей с PHP 5.5
PHP 5.5 представил функции хеширования паролей, которые вы можете использовать для упрощения вышеуказанного метода хеширования:
И проверяя:
Смотрите также:
password_hash()
,password_verify()
источник
$iv_size = 16;
я бы использовал:,$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length("AES-256-CBC"))
чтобы указать связь между размером iv для использования с используемым шифром. Вы также можете немного расширить информацию о необходимости (или отсутствии)pkcs7_pad()
/pkcs7_unpad()
или просто упростить сообщение, избавившись от них и используя «aes-256-ctr». Отличный пост @ Ja͢ckЯ думаю, что на это уже был дан ответ ... но в любом случае, если вы хотите зашифровать / расшифровать данные, вы не можете использовать SHA256
источник
Предпосылки ответа и объяснение
Чтобы понять этот вопрос, вы должны сначала понять, что такое SHA256. SHA256 - это криптографическая хеш-функция . Криптографическая хеш-функция - это односторонняя функция, вывод которой криптографически безопасен. Это означает, что легко вычислить хэш (эквивалентно шифрованию данных), но трудно получить исходный ввод с использованием хеша (эквивалент расшифровки данных). Поскольку использование криптографической хэш-функции означает, что дешифрование невозможно с вычислительной точки зрения, поэтому вы не можете выполнить дешифрование с помощью SHA256.
Вы хотите использовать двустороннюю функцию, а точнее блочный шифр . Функция, позволяющая как шифрование, так и дешифрование данных. Функции
mcrypt_encrypt
иmcrypt_decrypt
по умолчанию используют алгоритм Blowfish. Использование mcrypt в PHP можно найти в этом руководстве . Также существует список определений шифров для выбора шифра, который использует mcrypt. Вики по Blowfish можно найти в Википедии . Блочный шифр шифрует вход в блоках известного размера и положения с известным ключом, так что данные могут быть позже дешифрованы с помощью ключа. Это то, что SHA256 не может вам предоставить.Код
источник
Вот пример использования openssl_encrypt
источник
mcrypt_create_iv()
я бы использовал:,openssl_random_pseudo_bytes(openssl_cipher_iv_length($encryptionMethod))
таким образом методология работает для любого значения $ encryptionMethod и будет использовать только расширение openssl.false
дляopenssl_decrypt()
. См. Stackoverflow.com/q/41952509/1066234 Поскольку блочные шифры, такие как AES, требуют, чтобы входные данные были точно кратными размеру блока (16 байтов для AES), необходимо заполнение.источник
Мне потребовалось довольно много времени, чтобы понять, как не получить
false
при использованииopenssl_decrypt()
и получить шифрование и дешифрование.Если вы хотите передать зашифрованную строку через URL-адрес, вам необходимо указать URL-адрес строки:
Чтобы лучше понять, что происходит, прочтите:
Чтобы сгенерировать ключи длиной 16 байт, вы можете использовать:
Чтобы увидеть сообщения об ошибках openssl, вы можете использовать:
echo openssl_error_string();
Надеюсь, это поможет.
источник