Шифровать базу данных MySQL

Я пытаюсь создать платформу для пользователей, которые будут хранить конфиденциальные данные о своих клиентах. Контекст довольно прост: французские законы запрещают мне иметь доступ к данным, которые будут хранить мои пользователи (например, медицинские записи пациентов).

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

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

Проблема в том, что я понятия не имею, с чего начать, как это сделать … и даже не знаю, что искать в Google. Я даже пытался найти что-то подходящее на codecanyon.net, например, и не смог найти подходящих скриптов.

Заранее спасибо 🙂 !

PS: У меня действительно будет такая же проблема с файлами (jpg, word, pdf, xls … этого должно быть достаточно для пользователей). Но это другая история.

4

Решение

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

Однако я считаю, что вы упускаете важный момент: если у вас нет доступа к определенным данным, эти данные НЕ ДОЛЖНЫ поступать в вашу организацию в простом формате. Период. Если это так, то у вас уже есть доступ к нему. Таким образом, решения на основе php (или любого другого типа шифрования на основе сервера) или mysql находятся вне поля зрения.

Единственное решение, о котором я могу подумать, — это совместная работа со сторонним поставщиком PKI, который предоставит вашим клиентам сертификаты (возможно, на чип-картах), а клиентская часть вашего приложения шифрует конфиденциальные элементы личных данных на клиентском ПО ДО они отправляются на ваш сервер, а также расшифровывают эти элементы данных на клиенте. Это также означает, что вам придется использовать некоторые плагины на стороне клиента, если вы хотите, чтобы эта система работала в сети. Возможно, вам понадобится подписанное Java-приложение для управления кард-ридером и сертификатом.

Установка имеет 2 недостатка для ваших клиентов:

  1. Это не единственный поставщик, с которым они имеют дело, поскольку поставщик PKI должен быть независимой третьей стороной. Вы не должны управлять сертификатами.
  2. В случае повреждения хранимых данных зашифрованные данные будут потеряны. Итак, вам придется реализовать какое-то безумное решение для резервного копирования и восстановления.
6

Другие решения

Итак, предположим, что проблема заключается в следующем:

  • Вам необходимо зашифровать данные перед их сохранением.
  • У вас не должно быть ключей для его расшифровки, только для шифрования.

На самом деле есть инструмент для этого: он называется API уплотнения, и это может быть достигнуто через OpenSSL или Libsodium.

Запечатывание / Распечатывание Данных в PHP с Libsodium

$store_me = \Sodium\crypto_box_seal(
$plaintext,
$recipient_public_key
);

$visible = \Sodium\crypto_box_seal_open(
$store_me,
$recipient_keypair
);

Запечатывание / Распечатывание Данных в PHP с OpenSSL

/**
* A human-usable variant of openssl_seal()
*
* @param string $plaintext Your message
* @param string $publickey_string PEM-encoded RSA public key
* @param boolean $encode Hex-encode the output?
*
* @return string
*/
function easy_seal($plaintext, $publickey_string, $encode = false)
{
$pubkey = openssl_get_publickey($publickey_string);
if ($pubkey === false) {
throw new Exception('Could not load public key');
}
$sealed = '';
$ekeys = [];
$result = openssl_seal($plaintext, $sealed, $ekeys, [$pubkey]);
if ($result === false) {
throw new Exception('openssl_seal failed!');
}
if ($encode) {
return json_encode([
bin2hex($sealed),
bin2hex($ekeys[0])
]);
}
return json_encode([$sealed, $ekeys[0]]);
}

/**
* Inverse operation of easy_seal()
*
* @param string $ciphertext (the output of easy_seal())
* @param string $privatekey_string PEM-encoded RSA private key
* @param boolean $encoded Do we need to decode from hex?
*
* @return string
*/
function easy_unseal($ciphertext, $privatekey_string, $encoded = false)
{
list($sealed, $ekey) = json_decode($ciphertext, true);
if ($encoded) {
$sealed = hex2bin($sealed);
$ekey = hex2bin($ekey);
}
$open_data = '';
$privkey = openssl_get_privatekey($privatekey_string);
if ($privkey === false) {
throw new Exception('Could not load public key');
}

$result = openssl_open($sealed, $open_data, $ekey, $privkey);
if ($result === false) {
throw new Exception('openssl_open failed!');
}
return $open_data;
}

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

$public_key = file_get_contents('/path/to/publickey.pem');
$plaintext = 'Something something dark side';
$store_me = easy_seal($plaintext, $public_key);

// Elsewhere:
$secret_key = file_get_contents('/path/to/secretkey.pem');
$visible = easy_unseal($store_me, $secret_key);

Демо-версия: https://3v4l.org/BNavp

2

На самом деле, я также нахожусь в подобном проекте, где я пытаюсь создать безопасную базу данных в MySQL Server, которая также полезна для запуска всех допустимых SQL-запросов. Это все еще в процессе, и там слишком много трудностей; Я согласен.

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

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

  2. Второй способ заключается в том, что вы генерируете случайный ключ для каждого отдельного пользователя, например, во время регистрации. А данные другого пользователя может просматривать только тот пользователь, у которого есть ключ для его расшифровки, который здесь есть только у пользователя. И тогда вы применяете первый подход после этого. то есть вы выбираете ключ, который будет использоваться для шифрования этих ключей разных пользователей. а затем сохранить этот зашифрованный ключ в базе данных в отдельной таблице. Таким образом, в следующий раз, когда пользователь попытается получить доступ к его / ее данным, его введенный ключ (может быть его паролем) будет зашифрован с вашим решенным статическим ключом, если этот зашифрованный ключ будет найден в таблице вашей базы данных, вы получите данные этого пользователя, расшифруйте его своим ключом и покажите ему.
    Все, что вам нужно, это,
    (я) платформу программирования, чтобы выбрать, JAVA является лучшим.
    (ii) научиться использовать базу данных с этим языком программирования, MySQL Server — хороший выбор для работы.
    (iii) И хороший алгоритм шифрования для реализации.

Надеюсь, я не разозлил тебя этим ответом 🙂 Ура.

0