Похоже, что вы, возможно, захотите сделать еще какой-нибудь фон на крипто в целом, а также опции шифрования БД (вы не упомянули хранилище данных, но там являются параметрами MySQL и Postgres для полного шифрования). В общем, почти всегда плохая идея «сворачивать свои собственные», и, к сожалению, между функциями mcrypt() и openssl _ *() есть откровенно слишком много вариантов, представленных новичкам (например, представление EBC и CBC в равной степени действительные параметры). Хотя этот поток: https://security.stackexchange.com/questions/18197/why-shouldnt-we-roll-our-own в основном говорит о тщетности создания «новых» криптографических примитивов, этот принцип также применяется к наивным попыткам внедрения шифрования на уровне приложений и баз данных.
Как практический вопрос, наиболее сложной задачей, с которой вам, вероятно, придется столкнуться, является проблема управления паролями/ключами. Приведенный ниже код ставит всю ответственность на клиента (отправителя) - и если вы не сохраните предоставленный пароль (какой вид поражения цели), если пользователь забывает или иным образом не может предоставить свой пароль в будущем, зашифрованные данные в базе данных будет unrecoverable. (И, да, если вы действительно хотите спуститься по пути Яковского бритья, есть варианты для шифрования с несколькими ключами).
Если вы храните ключ/сервер на стороне сервера, вы в лучшем случае помещаете небольшую дорожную шину на пути противника: если ей удастся прочитать ваш ключевой файл, она может получить данные. Но в худшем случае, сохраняя пароль локально, вы даете ложное представление о безопасности своим пользователям, и если это финансовая, медицинская или иная защищенная информация, вы и ваша организация берете на себя бремя этой ответственности.
Наконец, есть зрелая библиотека здесь: http://phpseclib.sourceforge.net/crypt/examples.html, но, на мой взгляд, она предлагает слишком много возможностей для начинающего пользователя (см., Например, режим EBC по умолчанию в генераторе кода). Для пароль хеширования, внимательно ознакомьтесь с библиотекой phpPass здесь: http://www.openwall.com/phpass/.
Все, что сказано, представляет собой рабочий старт для простого двухстороннего, достаточно сильного шифрования со случайными генерируемыми векторами и солями инициализации и 256-битным AES-симметричным (например, не открытым ключом) шифрованием. Протестировано на OSX Lion & CentOS/RedHat 6.
Удачи!
//$message = escapeshellarg($_POST['message']);
$message = 'This is my very secret data SSN# 009-68-1234';
// Set to some reasonable limit for DB.
// Make sure to size DB column +60 chars
$max_msg_size = 1000;
$message = substr($message, 0, $max_msg_size);
// User's password (swap for actual form post)
//$password = escapeshellarg($_POST['password']);
$password = 'opensesame';
// Salt to add entropy to users' supplied passwords
// Make sure to add complexity/length requirements to users passwords!
// Note: This does not need to be kept secret
$salt = sha1(mt_rand());
// Initialization Vector, randomly generated and saved each time
// Note: This does not need to be kept secret
$iv = substr(sha1(mt_rand()), 0, 16);
echo "\n Password: $password \n Message: $message \n Salt: $salt \n IV: $iv\n";
$encrypted = openssl_encrypt(
"$message", 'aes-256-cbc', "$salt:$password", null, $iv
);
$msg_bundle = "$salt:$iv:$encrypted";
echo " Encrypted bundle = $msg_bundle \n\n ";
// Save it... (make sure to use bind variables/prepared statements!)
/* db_write("insert into sensitive_table encrypted_msg values (:msg_bundle)",
$msg_bundle); */
Теперь получить его: выход
// Retrieve from DB...
//$password = escapeshellarg($_POST['password']);
$password = 'opensesame';
// Swap with actual db retrieval code here
//$saved_bundle = db_read("select encrypted_msg from sensitive_table");
$saved_bundle = $msg_bundle;
// Parse iv and encrypted string segments
$components = explode(':', $saved_bundle);;
var_dump($components);
$salt = $components[0];
$iv = $components[1];
$encrypted_msg = $components[2];
$decrypted_msg = openssl_decrypt(
"$encrypted_msg", 'aes-256-cbc', "$salt:$password", null, $iv
);
if ($decrypted_msg === false) {
die("Unable to decrypt message! (check password) \n");
}
$msg = substr($decrypted_msg, 41);
echo "\n Decrypted message: $decrypted_msg \n";
Пример:
Password: opensesame
Message: This is my very secret data SSN# 009-68-1234
Salt: 3f12ce187d5c5bcc3b0d5acf1e76fad8b684ff37
IV: 00c1d3b4c6a6f4c3
Encrypted bundle = 3f12ce187d5c5bcc3b0d5acf1e76fad8b684ff37:00c1d3b4c6a6f4c3:KB6k+GlM+0EHbETUgEe8Lck0nF5qBz+51wc5LtmS4XMOm0Pfyyr2PIXMVEyzs/41
array(3) {
[0]=>
string(40) "3f12ce187d5c5bcc3b0d5acf1e76fad8b684ff37"
[1]=>
string(16) "00c1d3b4c6a6f4c3"
[2]=>
string(64) "KB6k+GlM+0EHbETUgEe8Lck0nF5qBz+51wc5LtmS4XMOm0Pfyyr2PIXMVEyzs/41"
}
Decrypted message: This is my very secret data SSN# 009-68-1234
Поиск алгоритма симметричного шифрования AES – Patashu
@Patashu Документация для расшифровки функций AES на php.net: http://www.php.net/manual/en/function.mcrypt-decrypt.php является недокументированной о том, как реально реализовать эти функции. Не могли бы вы пролить свет, если я получу успешную функцию шифрования? –
Вы должны прочитать литературу о том, как работают симметричные функции шифрования и AES. Тогда все параметры этой функции будут очевидны. – Patashu