php - 从MySQL普通数据库值迁移到完全AES加密的值(PHP APi)

标签 php mysql encryption migration

短:

根据GDPR法规,从纯文本数据库值迁移到完全/完全加密的值的最佳方法?

解释器:

我刚刚收到一个“警告”,由于GDPR(欧盟通用数据保护法规)合法要求的新的“设计隐私”概念,所有“敏感”信息都必须加密。这包括名称,地址,社交媒体资料等。

我们目前正在为2000+用户运行一个完整的生产数据库,只能通过我们的PHP REST API进行访问,该API用作所有Web和移动应用程序的入口点(尚无第三方开发人员)。该数据库包含当前以纯文本格式存储的电子邮件地址,地址,社交媒体句柄,名称,ip地址..(基于安全的敏感信息,例如密码,令牌,。或用于身份验证的任何其他值除外) /标识)。

由于市长对性能,搜索算法,整个PHP API等的影响(就像整个优化和“完美设置的数据库”的结尾),我不赞成这样做(在开发方面),但是由于这是必需的由于这是额外的保护层,因此我全力以赴。

现在,我主要关心的是..一切都在正常运行,我们不能只是说“好,关闭服务器,加密所有内容,部署新的API版本,然后重新打开。”而且,我认为这种迁移不能“一步一步地完成”,所有事情必须一次完成。如果API尚未准备好在所有查询中处理解密,则不能对数据库值进行加密,反之亦然,如果API希望对所有内容进行加密,则数据库不能是纯文本。

(我很高兴我将整个API类型的交易作为数据库的唯一输入/读取点,没有自定义脚本/连接,因此这很轻松)

我们正在运行一台性能非常强大的VPS服务器,因此由于冗余检查和其他原因而导致的性能损失会有所增加,并且我们也在运行登台/开发环境,因此测试就没有问题。

我将让MySQL为每条基于ID(主键)和创建时间戳(例如,两个值都不会改变)的组合创建的记录使用唯一键来处理AES(这可能不是那么聪明。万一“由于某种原因”该值确实改变了,这个想法就消失了,数据就消失了。所以不确定),以便我的PHP应用程序在运行查询时不需要以纯文本形式传递键,但是再次, “用于解密的密钥的创建”在查询日志等中仍然可见,因此“最安全”的方法是让PHP应用程序加密和解密所有传入/传出的数据,但这将导致无法例如运行“搜索查询”(除非我在这些特定查询中发送密钥。)。

我的问题:

一个人怎么会这样呢?我应该让PHP处理加密/解密还是首选的MySQL?请求记录时,是否有一种可行的方法可以迁移到加密值? ..?

我的想法是不影响任何数据库值(除了更新每个非整数列以处理当前指定字符数的2-3倍外),这可以在不影响生产的情况下完成。然后逐步更新所有API查询,以检查所选值是否已加密。当一个部分运行正常时,更新该部分的表以加密所有值。作为一个简单的例子

MySQL方式每个SELECT查询:

SELECT IF_AES_ENCRYPTED(first_name, AES_DECRYPT(first_name), first_name) AS first_name FROM contacts WHERE id = 1;


(或)PHP方式:数据检索:

while ($row = $result->fetch_assoc()) {
  $contact->setFirstName((IS_AES_ENCRYPTED($row['first_name']) ? AES_DECRYPT($row['first_name']) : $row['first_name']);
}


部署结束时:

UPDATE contacts SET first_name = AES_ENCRYPT(first_name);


肯定有一些方法可以完成此操作,但是由于我是此时此刻的唯一开发人员,因此我不确定执行此操作的最实用/最有效的方法是什么,或者我是否过度或在考虑中或不。只是寻找在那里执行了迁移/更新的其他开发人员。

谢谢,伯特。

最佳答案

我可以通过添加新列first_name_enc来存储字符串的加密版本来实现。

然后,您可以在过渡到完全加密时临时存储加密和未加密的值。

ALTER TABLE contacts ADD COLUMN first_name_enc VARBINARY(...);


当您读取值时,请解密它,但是如果值是NULL,则它必须是尚未转换的行,因此请退回到原始的未加密列。

SELECT COALESCE(AES_DECRYPT(first_name_enc, <key-string>), first_name) ...


在整个应用程序中放置此代码之后,可以开始批量转换行:

UPDATE contacts SET
  first_name_enc = AES_ENCRYPT(first_name, <key-string>), 
  first_name = NULL
WHERE id BETWEEN 1 AND 1000;


在将所有内容都转换为加密后,并且您的应用程序不再插入未加密的列之后,可以将条件查询转换为简单地读取加密的列并对其进行解密。

SELECT AES_DECRYPT(first_name_enc, <key-string>) ...


然后,最后删除未加密的列,因为它们现在仅包含NULL。

ALTER TABLE contacts DROP COLUMN first_name;




我建议您在投入大量时间进行这项工作之前,先确认您真正需要进行的加密工作。我读过一些文章,声称GDPR实际上并未强制加密。 https://www.i-scoop.eu/gdpr-encryption/

但是,带一些盐的互联网文章。咨询合格的专家。即使向专业专家支付了咨询费,也可以为您节省数万美元的软件开发成本!

关于php - 从MySQL普通数据库值迁移到完全AES加密的值(PHP APi),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59647500/

相关文章:

php - PRE 标记到纯文本

javascript - Json,获取另一个级别内的信息

PHP artisan循环数组错误

MySQL 的 PHP 搜索引擎

php - 将您的表单字段命名为与 mysql 相同的名称实际上会带来任何安全风险吗?

Java文件交换教程: why put the document in a jar before encryption?

php - 试图制作一个名为 "List"的 CodeIgniter Controller

php - 我应该制作另一个表格还是只使用数组? (归一化或不归一化)

security - 编写自己的加密是否违法?

php - 如何解密Zend2加密数据?