简体   繁体   English

从 MySQL 纯数据库值迁移到完全 AES 加密的值 (PHP APi)

[英]Migrating from MySQL plain database values to fully AES encrypted values (PHP APi)

Short:短的:

Best way to migrate from plain-text database values to fully/entirely encrypted values due to GDPR regulations?由于 GDPR 法规,从纯文本数据库值迁移到完全/完全加密值的最佳方法是什么?

Explainer:讲解员:

I just received a "heads-up" that due to the new "Privacy by design" concept legally required by the GDPR (The EU General Data Protection Regulation) all 'sensitive' information is required to be encrypted.我刚刚收到一个“提示”,由于 GDPR(欧盟通用数据保护条例)法律要求的新“设计隐私”概念,所有“敏感”信息都需要加密。 This includes names, addresses, social media profiles, ..这包括姓名、地址、社交媒体资料、..

We are currently running a full production database for 2000+ users, only accessible via our PHP REST API that is used as entry point for all web and mobile application (no third-party developers yet).我们目前正在为 2000 多个用户运行一个完整的生产数据库,只能通过我们的 PHP REST API 访问,该 API 用作所有 Web 和移动应用程序的入口点(尚无第三方开发人员)。 This database contains email addresses, addresses, social media handles, names, ip-addresses .. that are currently stored in plain-text (except for security-based sensitive information like the passwords, tokens,.. or any other value used for authentication/identification).该数据库包含当前以纯文本形式存储的电子邮件地址、地址、社交媒体句柄、名称、IP 地址......(除了基于安全的敏感信息,如密码、令牌......或用于身份验证的任何其他值/鉴别)。

I'm not a big fan of this (development wise) because of the mayor impact on performance, search algorithms, the whole PHP API etc (feels like an end of the whole optimized and "perfectly setup database"), but since it's required and since it's an extra layer of protection, I'm all in for it.我不是这个(开发明智的)的忠实粉丝,因为它对性能、搜索算法、整个 PHP API 等的主要影响(感觉就像整个优化和“完美设置数据库”的结束),但因为它是必需的因为它是额外的保护层,所以我全力以赴。

Now, my main concern is.. everything is actively running and we can't just say "okay, shutting down the server, encrypt everything, deploy the new API version and turn it back on again.".现在,我主要关心的是..一切都在积极运行,我们不能只是说“好吧,关闭服务器,加密一切,部署新的 API 版本并重新打开它。”。 Also, this migration can't be done "step by step along the way" I think, everything has to be done all at once.此外,我认为这种迁移不能“一步一步”完成,所有事情都必须一次完成。 The database values can't be encrypted if the API isn't ready to handle decryption within all queries, and vice-versa, the database can't be plain text if the API is expecting everything to be encrypted.如果 API 未准备好处理所有查询中的解密,则无法加密数据库值,反之亦然,如果 API 期望对所有内容进行加密,则数据库不能是纯文本。

(I'm glad I went for the whole API type of deal to be the only point of entry/read for the database, no custom scripts/connections, so this is a relieve) (我很高兴我将整个 API 类型的交易作为数据库的唯一入口/读取点,没有自定义脚本/连接,所以这是一种解脱)

We're running a highly overpowered VPS server, so a bit of performance-loss due to redundant checks and whatnot is an option and we're running staging/dev environments as well, so testing is no issue.我们正在运行一个功能强大的 VPS 服务器,因此由于冗余检查和诸如此类的东西是一种选择,因此会造成一些性能损失,而且我们也在运行暂存/开发环境,因此测试没有问题。

I would let MySQL handle the AES with a unique key for every record that is based on a combination of the ID (primary key) and the creation timestamp for example (both values that will never change) (which might not be that smart of an idea in case "for some reason" this value does changes, the data is gone.. so not sure about that), so that my PHP application doesn't need to communicate the key in plain text when running queries, but then again, the 'creation of the key for decryption' will still be visible within the query logs etc, so the "most secure" way would be to let the PHP application encrypt and decrypt all incoming/outgoing data, but this would result in not being able to run 'search queries' for example (unless I send the key within those specific queries..).例如,我会让 MySQL 使用基于 ID(主键)和创建时间戳的组合的每个记录的唯一键来处理 AES(这两个值都不会改变)(这可能不是那么聪明)想法万一“出于某种原因”这个值确实改变了,数据消失了..所以不确定),所以我的PHP应用程序在运行查询时不需要以纯文本形式传达密钥,但又一次, “创建用于解密的密钥”仍将在查询日志等中可见,因此“最安全”的方法是让 PHP 应用程序加密和解密所有传入/传出数据,但这将导致无法例如,运行“搜索查询”(除非我在这些特定查询中发送密钥......)。

My question:我的问题:

How would one go about this..?怎么办呢..? Should I let PHP handle the en/decryption or preferable MySQL?我应该让 PHP 处理加密/解密还是更可取的 MySQL? Is there a usable way to migrate to encrypted values along the way when the record gets requested?当记录被请求时,是否有一种可用的方法可以沿途迁移到加密值? ..? ..?

My idea was to no touch any database values (except for updating every non-integer column to handle 2-3x the amount of characters that are currently specified) which can be done without having an impact on production.我的想法是不接触任何数据库值(除了更新每个非整数列以处理当前指定的字符数量的 2-3 倍),这可以在不影响生产的情况下完成。 Then updating all the API queries, step by step, to check if the selected value is encrypted or not.然后逐步更新所有 API 查询,以检查所选值是否已加密。 And when one section is running OK, update the table for that section to encrypt all the values.当一个部分运行正常时,更新该部分的表以加密所有值。 As a (simple) example作为一个(简单的)例子

MySQL-way; MySQL方式; Every SELECT query:每个 SELECT 查询:

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

(or) PHP-way: Retrieving of data: (或)PHP 方式:检索数据:

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

At the end of the deployment:在部署结束时:

UPDATE contacts SET first_name = AES_ENCRYPT(first_name);

There are definitely ways to accomplish this, but since I'm the only developer here at this point, I'm just not sure what would be the most practical/efficient way to do this or if I'm over- or under thinking this or not.肯定有方法可以做到这一点,但由于我是此时唯一的开发人员,我只是不确定最实用/最有效的方法是什么,或者我是否过度或低估了这一点或不。 Just looking for other developers out there that have executed a migration/update like this.只是寻找其他已经执行过这样的迁移/更新的开发人员。

Thanks, Bert.谢谢,伯特。

I would do this by adding a new column first_name_enc to store the encrypted version of the string.我会通过添加一个新列first_name_enc来存储字符串的加密版本来做到这一点。

Then you can store both encrypted and unencrypted values temporarily while you are transitioning to fully encrypted.然后,您可以在过渡到完全加密时临时存储加密和未加密的值。

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

When you read the values, decrypt it, but if the value is NULL, then it must be a row that hasn't been converted yet, so fall back to the original unencrypted column.当您读取值时,对其进行解密,但如果该值为 NULL,则它必须是尚未转换的行,因此请回退到原始未加密列。

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

After you put this code in place throughout your application, then you can start converting the rows in batches:在整个应用程序中放置此代码后,您就可以开始批量转换行:

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

After you finish converting everything to encrypted, and your application is no longer inserting to the unencrypted columns, then you can convert the conditional queries to simply read the encrypted columns and decrypt them.完成将所有内容转换为加密后,您的应用程序不再插入未加密的列,然后您可以将条件查询转换为简单地读取加密列并解密它们。

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

Then finally drop the unencrypted columns, since they now contains only NULLs anyway.然后最后删除未加密的列,因为它们现在只包含 NULL 值。

ALTER TABLE contacts DROP COLUMN first_name;

I recommend before investing time into this work that you confirm what you're really required to do regarding encryption.我建议您在投入时间从事这项工作之前确认您真正需要做的有关加密的工作。 I've read articles that claim that the GDPR doesn't actually make encryption mandatory.我读过一些文章声称 GDPR 实际上并未强制要求加密。 https://www.i-scoop.eu/gdpr-encryption/ https://www.i-scoop.eu/gdpr-encryption/

But take internet articles with a grain of salt.但对互联网文章持保留态度。 Consult a qualified expert.咨询合格的专家。 Even paying a professional expert a consultation fee might save you tens of thousands in software development costs!即使向专业专家支付咨询费,也可能为您节省数万美元的软件开发成本!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM