问题 什么是在MySQL中使用/存储加密密钥的最佳方法


我打算使用MySQL及其内置的加密功能来加密/解密某些表中的某些列。我担心的是我需要将密钥存储在某个地方。我当然可以将密钥存储在一个文件中并控制该文件的权限以及访问它的应用程序的权限,但这还够吗?我也可以创建一个Web服务来获取密钥或其他东西。

我在一个小商店里,我将是唯一可以访问应用程序所在机器的人(可能是另一个人)。 编辑:我应该补充说,除非我添加了一个层,否则这个应用程序的Web部分需要解密数据。 

我看起来很恶心,但似乎没有人有一个防弹的答案。

这是你必须满足的那些问题吗?鉴于我正在使用MySQL和PHP(可能是Python),有更好的方法来解决这个问题吗?


5795
2017-10-24 01:43


起源

加密列的目的是什么?当然,聪明的做法是通过您的应用程序加密行的敏感数据,并将行与盐一起存储,以便更难解密。 - Aupajo
我想我的意思是使用AES_ENCRYPT加密每行中的某个字段。所以让应用程序加密和解密比MySQL函数更好,或者你只是说我在调用MySQL函数时应该为每一行都有一个唯一的盐键 - Chris Kloberdanz


答案:


我不确定使用MySQL内置加密是否是解决问题的最佳方案。

PHP的 M_CRYPT 软件包被认为是非常好的,它使您可以灵活地选择最适合您需求的算法。

将密钥存储在其他服务器上有一个很大的优点:密钥与加密数据不在同一台机器上*)。因此,只要攻击者对受感染的计算机没有足够的控制权,他们就无法获得密钥。
如果攻击者获得对存储数据的机器的完全控制,他们很可能能够在网络服务中查询密钥。

但是,将密钥从一台机器传输到另一台机器会打开一个需要保护的整个新区域。可能涉及更多密钥和更多加密层,从而增加了出错的可能性。

*) 另一种选择是在webserver启动时输入密码,并将其保留在内存中。

可能的方案
如果看到使用的解决方案使用以下方法为具有Web访问权限的用户加密文件(我不确定您的环境,但它可能会有所帮助):

  • 在创建用户时,将长随机密钥分配给新用户。
  • 该随机密钥存储在用户记录中的加密列中。
    只有这一列被加密,以免影响其余记录的性能!
  • 随机密钥列的加密使用1个主密码完成,存储在文件或内存中。
    更好的选择是在启动Web服务器时输入密码,并仅将其存储在内存中。
    另一种方法是让用户输入密码并使用它来加密/解密随机密钥列,但我不确定这是否会增加或减少安全性
  • 每个需要加密的文档都使用该用户的随机密钥加密,然后存储在磁盘上。
  • 文档以最小的权限存储在文件系统中。

这种方法的优点是:
1.随机密钥在数据库中加密。因此,您仍然可以增加数据库服务器的安全性,并与加密列结合使用。 2.文档存储有不同的密钥,如果攻击者获得密钥,则只有部分文档被泄露。

然而:
如果攻击者获得主密码并具有对用户表的读访问权,则整个系统再次被破坏。


7
2018-05-02 10:35





我可能会将它存储在一个非Web可访问目录中的文件中,并尽可能地锁定文件系统权限。

面向Web的脚本不应使用变量打开任何文件系统文件,尤其是用户提供的文件。甚至不要让他们选择滑过通过输入过滤器的东西(你正在过滤用户提供的数据吗?)并可能放弃密钥文件的内容。将文件路径保留为硬编码字符串和仅限于()。由于您的大多数数据都存储在MySQL中,因此这应该不是问题。

在进行解密时,将密钥读入一个干净的初始化变量,进行解密,然后覆盖密钥变量(比如用一串x),并取消设置变量。这可能听起来有点偏执但是如果你把键放在内存中的时间最小化并将它与PHP脚本周围的所有其他变量隔离它就不会让你任何  安全。

如果您和另外一个人是唯一可以物理访问机器的人,这可能就好了。如果有人闯入并窃取了这个盒子,那么,他们已经获得了所有数据,所以游戏结束了。


4
2017-10-24 08:56





您似乎正在考虑使用“特定于列”的密钥与“AES_ENCRYPT”和“AES_DECRYPT”一起使用。正如评论者所说,这是一个坏主意,因为任何入侵都可以访问所有数据。

如果您使用“用户提供的”密码,无论是否使用盐,您都会更加安全。

也就是说,如果加密密钥只能由使用它的应用程序读取,那么您可能“足够好”。如果机器被破坏,他们将使用一把钥匙更快地获得数据。


1
2017-10-24 03:02