Как зашифровать данные на php с помощью публичных / приватных ключей?

У меня есть небольшая строка некоторых данных (менее 1 КБ), которые я хотел бы, чтобы пользовательские агенты передавались на другие сайты, когда они отправляются с моего сайта. Чтобы другие сайты подтвердили, что я был тем, кто создал строку, я подумал о двух вариантах.

  1. Сервер отправляет мне ответный эхо-запрос для подтверждения (например, PayPal, OpenID и т. Д.)
  2. Я использую открытые / закрытые ключи, чтобы подтвердить отправку сообщения (например, PGP, DKIM и т. Д.)

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

Из этих двух вариантов кажется, что №2 позволит сэкономить на пропускной способности, что делает его лучшим выбором.

Итак, как вы можете настроить криптографию с открытым / закрытым ключом с помощью PHP и есть ли какие-либо недостатки?


person Xeoncross    schedule 07.01.2011    source источник


Ответы (5)


Я бы создал пару открытых / закрытых ключей S / MIME с помощью OpenSSL, а затем использовал бы команду OpenSSL для шифрования и дешифрования. Я считаю, что это лучше, чем использование PGP, потому что openssl включен в большинство операционных систем Linux, а PGP - нет. OpenSSL также основан на стандартах и, как правило, с ним легче работать, если у вас есть команды.

Я рекомендовал не использовать решение «на чистом PHP» (под чистым PHP я подразумеваю выполнение шифрования в PHP, а не использование PHP для вызова существующей библиотеки или отдельного исполняемого файла). Вы не хотите делать массовое шифрование на PHP. Слишком медленно. И вы хотите использовать OpenSSL, потому что это высокая производительность и безопасность хорошо понятны.

Вот и волшебство.

Чтобы создать ключ X.509:

$subj="/C=US/ST=California/L=Remote/O=Country Govt./OU=My Dept/CN=Mr. Agent/[email protected]"
openssl req -x509 -newkey rsa:1024 -keyout mycert.key -out mycert.pem -nodes -subj $subj

При этом закрытый ключ помещается в mycert.key, а открытый ключ - в mycert.pem. Закрытый ключ не защищен паролем.

Теперь, чтобы подписать сообщение с помощью S / MIME:

openssl smime -sign -signer mycert.pem -inkey mycert.key <input >output

Чтобы зашифровать сообщение с помощью S / MIME:

openssl smime -encrypt -recip yourcert.pem <input >output

Чтобы расшифровать сообщение с помощью S / MIME:

openssl smime -decrypt -inkey mycert.key -certfile mycert.pem <input >output

У меня также есть несколько демонстраций использования OpenSSL из привязок языка C, но не из PHP.

person vy32    schedule 14.01.2011
comment
Почему расширение OpenSSL PHP будет медленнее, чем вызов самого OpenSSL? В любом случае выполняется один и тот же код. Тем не менее, есть еще одна причина не делать это PHP-родным: расширение OpenSSL не может делать все, что может выполнять оболочка двоичного файла openssl при работе с экзотическими форматами ключей. - person Charles; 14.01.2011
comment
Второй комментарий Чарльза. Расширение PHP OpenSSL, вероятно, будет быстрее, а не медленнее, потому что оно использует те же API-интерфейсы, что и приложения командной строки openssl, но без дополнительных затрат на создание процесса. - person Artefacto; 14.01.2011
comment
О, я не знал, что у PHP есть расширения OpenSSL. Тогда тебе следует их использовать. У меня есть код C ++, который делает это; я должен опубликовать это? - person vy32; 15.01.2011
comment
Спасибо, что поделились, я попытался использовать это с новейшим OpenSSL, и вот несколько замечаний: 1) используйте -binary при расшифровке и шифровании, иначе в документах говорится, что OpenSSL может войти в файл и испортить окончания строк. 2) -recip никогда не работал у меня, я просто указывал имя файла сертификата в качестве последнего аргумента (как поддерживается OpenSSL) и использовал -in и -out вместо ‹›. 3) Кажется, не требуется -certfile на этапе дешифрования, достаточно -inkey. - person Cray; 18.08.2012
comment
Кроме того, для многих целей вы можете использовать -outform DER на этапе шифрования и -inform DER на этапе дешифрования, чтобы сохранить размер зашифрованного сообщения. (Сохраняет его в двоичном формате вместо base64.) - person Cray; 18.08.2012
comment
Это решение опасно для больших файлов ›~ 1,5 ГБ. Шифрование по-прежнему работает, но расшифровывать не удается. См.: проблема с расшифровкой больших файлов - person Ivin; 03.05.2021

Создание пары закрытого и открытого ключей с помощью функций PHP Openssl:

// Configuration settings for the key
$config = array(
    "digest_alg" => "sha512",
    "private_key_bits" => 4096,
    "private_key_type" => OPENSSL_KEYTYPE_RSA,
);

// Create the private and public key
$res = openssl_pkey_new($config);

// Extract the private key into $private_key
openssl_pkey_export($res, $private_key);

// Extract the public key into $public_key
$public_key = openssl_pkey_get_details($res);
$public_key = $public_key["key"];

Затем вы можете зашифровать и расшифровать, используя закрытый и открытый ключи, например:

// Something to encrypt
$text = 'This is the text to encrypt';

echo "This is the original text: $text\n\n";

// Encrypt using the public key
openssl_public_encrypt($text, $encrypted, $public_key);

$encrypted_hex = bin2hex($encrypted);
echo "This is the encrypted text: $encrypted_hex\n\n";

// Decrypt the data using the private key
openssl_private_decrypt($encrypted, $decrypted, $private_key);

echo "This is the decrypted text: $decrypted\n\n";
person Eborbob    schedule 09.02.2016
comment
Кто должен хранить открытый ключ, а кто - закрытый ключ? Должны ли мы давать клиенту открытый ключ или закрытый ключ? - person Phantom007; 08.02.2018
comment
Вы храните закрытый ключ сами, а даете кому-либо еще открытый ключ. - person Jeffiekins; 07.12.2018

Правило 1. Не реализуйте это самостоятельно, используйте библиотеку.

Какая библиотека? Вот мои рекомендуемые общедоступные PHP- ключевые библиотеки криптографии:

  1. Halite зависит от libsodium (но помимо безопасности подчеркивает простоту и удобство использования).
  2. libsodium из PECL
  3. EasyRSA, который реализует безопасное шифрование с открытым ключом и подписи с открытым ключом с использованием RSA в наиболее безопасных режимах (НЕ PKCS1v1.5, когда-либо!)
  4. phpseclib, который используется EasyRSA.

В общем, вам понадобится libsodium, если ваша цель - безопасность. Используете ли вы галит или нет - дело вкуса.

person Scott Arciszewski    schedule 09.12.2015
comment
В 2020 году не могли бы вы подробнее рассказать, в чем преимущество их использования перед встроенными функциями? - person Gregory Magarshak; 29.11.2020

PGP - хороший вариант - он реализован правильно и полностью (т.е. у вас мало места для ошибок безопасности с PGP). Я думаю, что этот вопрос SO поможет вам при взаимодействии с GnuPG. Вопрос в том, будут ли проверять вашу подпись и как другие сайты. Вам необходимо либо соответствовать их требованиям к механизму проверки, либо предоставить собственный модуль, который эти сайты будут использовать для проверки.

Также возможно, что вы можете использовать OAuth или OpenID для идентификации пользователей на этих других сайтах, но я не являюсь экспертом в этих технологиях.

person Eugene Mayevski 'Callback    schedule 07.01.2011

Я написал пример шифрования и дешифрования с помощью openSSL на PHP и Python.

http://glynrob.com/php/hashing-and-public-key-encryption/

Доступен исходный код Github.

Не забывайте, что закрытый ключ должен быть доступен в месте расшифровки, чтобы это работало.

person GlynRob    schedule 19.10.2013
comment
Эта ссылка glynrob.com/php/hashing-and-public-key-encryption ведет на страницу 404. - person Ankur; 05.05.2021