通过使用与用户自己的密码保护的私钥配对的公钥加密来保护Web应用程序数据库中的PII?

时间:2011-08-30 04:16:41

标签: mysql security encryption pii

目标:

我想允许用户在自定义Web应用程序(支持托管环境中的PHP / MySQL)中创建问题并从其他用户收集信息,并保护收集的数据。

背景

所有用户回答的默认问题都是通用的,不能被视为个人身份信息(PII),因此限制了我保护它的责任,但是创建自己问题的用户可能会要求PII然后变为PII责任。

我想要做的是以这样一种方式保护这些信息:如果主机帐户或数据库被泄露(或两者都有!),如果没有大量工作,PII将无法恢复,即便如此理论上只有一小部分可以恢复。

建议的解决方案:

假设MySQL的内置AES_ENCRYPT()/AES_DECRYPT()函数用于加密PII表,密码需要存储在托管帐户中,因此如果托管帐户遭到入侵,则可以轻松读取数据。 / p>

由于用户的密码受到良好保护(使用盐进行哈希处理),我正在考虑在身份验证期间捕获明文密码,对其进行加密,并将其存储在PHP会话中,直到用户注销为止。

将为每个用户创建一个公钥/私钥组合,其私钥由用户密码+ salt密码保护。

然后,当基于该用户的自定义问题的PII数据被添加到DB时,用户的公钥将用于加密他们通过应用程序收集的PII。读取数据时(仅当用户登录时),数据将使用用户的私钥(使用密码+盐解锁)解密。

我看到的好处是:

  1. 在最糟糕的情况下,服务器完全泄露,读取应用程序代码以查找加密密钥,解密PHP会话文件以查找用户密码,然后解密与该用户关联的PII表中的条目,然后只有从当前登录用户的问题中收集的PII才能被恢复。任何未登录的用户都是安全的。
  2. 即使是DBA或类似人员也无法阅读PII。
  3. 我看到的缺点是:

    1. 用户密码在登录时以可恢复的形式存储。
    2. 忘记密码的用户将无法访问他们的数据。
    3. 由于加密,每个相对较小的数据位将在数据库中占用更多空间。
    4. 我的问题:有更好的方法吗?

2 个答案:

答案 0 :(得分:7)

从安全角度来看,我看到了这个设计的一些问题。首先,密码绝不能加密,这是由CWE-257标识的漏洞。

更多MySQL的AES_ENCRYPT()完全是垃圾,原因不止一个。它使用EBC模式,这是一个很好的例子,说明为什么这是废话:

原始图片:

enter image description here

EBC模式(这是mysql的AES_ENCRYPT()使用的):

enter image description here

但是,如果数据库遭到入侵,则攻击者将通过启用query log来击败AES_ENCRYPT()

应该避免使用用户的密码进行加密,你应该使用crypgoraphic nonce。如果您确实使用了密码,请确保使用String2Key功能。您还必须使用带有random iv的CBC或CMAC模式。我真的没有看到非对称加密技术如何提供帮助。非对称加密非常缓慢,内存密集。当攻击者控制消息时,它们保护的数据会降低安全性,因为您可以比较密文消息。这就是随机IV is important的原因,并且在不对称的世界中你没有这种保护级别。

密钥生成应该类似于: $key=string2key($base_nonce.$salt.$user_password)

确保string2key函数的输出与键空间的大小相同。所以aes 128需要128位密钥。每个密码都应该有自己的$salt,而$base是存储在文本文件中的加密随机数。 (攻击者必须先读取此文件,然后才能破解密钥,如果此值大到128位,那么它就是一个有争议的点。)每条消息都需要自己的$iv,并且此值也必须是加密的nonce (类似于盐)。我会从$salt生成$iv$base_nonce/dev/urandom。 IV可以以明文形式存储在数据库的一列中,也可以与密文一起存储。

从法律角度来看,即使您构建安全的cryptogrpahic系统,您仍然会遇到内部威胁问题,如果服务器完全受损,所有数据仍然会受到影响。这真的不是一个工程问题。

对法律威胁的最佳防御是由熟练的律师撰写的强有力的条款和条件。

答案 1 :(得分:0)

我所关注的一个问题如下。 “任何未登录的用户都是安全的”部分过于乐观了。通过使用用户密码保护私钥,您可以打开各种密码强制攻击。不只是当前的会议,而是所有人。一个有效的方法就是简单地列举前100个常用密码,然后尝试对所有用户进行尝试。攻击者必然会发现一些密钥。 (我假设您要么将每用户随机盐与用户记录一起存储,攻击者可以看到,或者您有一个攻击者能够通过妥协获得的秘密盐。)