PHP、MySQL和AES加密/解密用户数据

4

我对AES加密还不熟悉,但尝试构建一个这样的解决方案:

  • 接受消费者数据
  • 使用AES和“公共”密钥加密该数据
  • 将该数据存储在MySQL数据库中
  • 仅能使用私钥(存储在我的个人计算机上而非服务器本身)拉取和解密数据。

我意识到这可能有点过度保护,但希望过度保护我的消费者数据。

需要注意以下几点:

  1. 这不是信用卡信息,请不要告诉我PCI-DSS,这是其他形式的个人信息,每个字段长度都不超过500个字符。
  2. 我可能会将消费者信息的某些部分存储在第二个数据库中,并通过唯一的成员ID进行关联,以提高安全性。
  3. 只能从我的静态IP直接向我的服务器发出MySQL调用。
  4. SSH root已禁用,端口已更改等等,因此我认为我的服务器防止任何“基本”误用的能力相当不错。

我已经在网上和SO上寻找文章,但没有找到如何完全将私钥保持在服务器之外的内容。即使我需要将其保存在服务器上,也希望得到如何继续前进的想法或建议。

编辑 - 澄清

为了更清楚地表达,我正在尝试实现以下目标(以非常基本的形式):

  • 客户在线输入其电话号码。

  • 使用密钥A在线加密输入的电话号码并将其存储在mysql数据库中。

  • 此时,客户将无法再看到完整的电话号码,但可以更新它(通过进行第n次密钥A过程)。

  • 作为系统管理员,我只能通过下载并在我的本地计算机上解密数据来访问数据(或者我必须首先上传一个临时文件,然后用它来解密我需要的数据)。

编辑2 - 我是个白痴

我正在使用Andrew Cooper的下面的响应,但是在让我的脚本读取我生成的.pem文件的内容时遇到了麻烦。根据下面的代码 - 我该如何使$public key对应于我服务器上特定的.pem文件?

<?php

if (isset($_SERVER['HTTPS']) )
{
    echo "SECURE: This page is being accessed through a secure connection.<br><br>";
}
else
{
    echo "UNSECURE: This page is being access through an unsecure connection.<br><br>";
}


// Create the keypair
$res=openssl_pkey_new();

// Get private key
openssl_pkey_export($res, $privatekey);

// Get public key
$publickey=openssl_pkey_get_details($res);
$publickey=$publickey["key"];

echo "Private Key:<BR>$privatekey<br><br>Public Key:<BR>$publickey<BR><BR>";

$cleartext = '1234 5678 9012 3456';

echo "Clear text:<br>$cleartext<BR><BR>";

openssl_public_encrypt($cleartext, $crypttext, $publickey);

echo "Crypt text:<br>$crypttext<BR><BR>";

openssl_private_decrypt($crypttext, $decrypted, $privatekey);

echo "Decrypted text:<BR>$decrypted<br><br>";
?>

编辑3 - 可能不是“白痴”,而是分号讨厌我

我的分号错位了。我正在使用函数:file_get_contents(),但读取.pem文件的数据是否有更优选的方法?

3个回答

6
您应该能够在个人计算机上生成公钥/私钥对,然后在应用程序中发布公钥,以便可以加密数据。这样,服务器永远不会看到私钥,如果服务器被黑客攻击,则数据仍然安全。
您需要确保整个交易都在SSL上进行。客户端可以生成随机会话密钥,使用该密钥加密数据(使用AES),然后使用应用程序中的公钥(使用RSA)加密密钥,并将加密的数据和密钥发送到服务器。您可以将整个数据块存储在一个或两个数据库字段中。唯一解密数据的方法是首先解密密钥,而唯一的方法是使用个人计算机上的私钥。
更新
请查看http://plugins.jquery.com/project/jQuery-Gibberish-AES。 这是一个JQuery插件,似乎允许此类情况。 我没有使用它的经验,但我认为这是一个很好的开始。
新更新
只是为了明确我的建议,并回答您的编辑:
你不能只使用AES加密。使用AES时,有一个密钥用于加密和解密。该密钥必须存在于进行加密操作的任何地方,无论是在客户端代码中还是在Web服务器上。在第一种情况下,任何人都可以获得您的密钥。在第二种情况下,如果Web服务器受到攻击,则密钥和数据也处于风险之中。
解决方案是将强大的AES加密与公钥加密(RSA)结合使用。我建议在客户端执行加密操作,原因如下所述。以下是我建议采取的步骤:
  1. 在您的私人计算机上创建公钥/私钥对,并保护好私钥。
  2. 将公钥放置在发送给客户端的代码中。
  3. 当用户提交表单时,客户端代码执行以下操作:
    1. 生成一个随机的AES密钥(会话密钥)
    2. 加密表单数据
    3. 使用您的公钥和RSA算法来加密会话密钥
    4. 丢弃明文会话密钥
    5. 将加密的表单数据和加密的会话密钥发送到您的服务器
  4. 您的服务器接受加密的表单数据,并将其与加密的密钥一起存储在数据库中。

现在,您在数据库中拥有加密数据,只能使用存储在您的私人计算机上的私钥检索。即使用户在其计算机上明文捕获会话密钥,最坏的情况也只是可以解密那条记录。

我建议采用客户端方法,这样您的服务器就永远不会看到明文加密密钥。如果在服务器端使用相同的方案,则理论上攻击者可以坐在您的服务器上观察发生的情况。归根结底,这基本上取决于您想要多么偏执。
按照此方案,当您要检索数据时,您将从数据库中以加密形式将所需数据转储到您的私人计算机中。然后对于每个加密数据块:
1. 使用RSA算法和您的私钥解密会话密钥 2. 使用步骤1中的会话密钥使用AES解密数据
总之,这是我建议的方法。我相信有库可以处理这个问题。

我不确定这该怎么做:AES_ENCRYPT函数只需要一个字符串和一个密钥就可以进行加密。任何有密钥访问权限的人都可以访问密钥加密的blob中所包含的内容。那么服务器如何在没有密钥的情况下进行加密呢? - cwallenpoole
@Christopher W. Allen-Poole - 你假设加密是在服务器上进行的。如果它是在客户端上进行的,然后客户端发送加密数据和使用公钥加密的密钥,那么服务器上就没有任何可以解密它的内容。服务器不需要知道用于加密数据的会话密钥。 - Andrew Cooper
@Andrew Cooper - 我看了一下那些乱码的 jQuery 代码,但好像并没有按照所述的那样运行,而且那个“文档”写得很糟糕。我已经添加了一个新的编辑来进一步解释我的目标。 - JM4
@JM4: 我之前说过,我对Gibberish没有任何经验——只是通过Google找到的。我相信有一些工具可以帮助你。请查看我的更新,以获得更详细的解释和建议。 - Andrew Cooper
@Andrew Cooper - 我已经开始按照你的方法进行了,我确实最喜欢它。如果你有时间,能否看一下我最近的编辑? - JM4
显示剩余2条评论

2
使用AES和“公共”密钥对数据进行加密,仅能使用私钥解密数据。但是,AES是对称加密算法,即加密和解密使用相同的密钥。或者您是想实现类似SSL的东西,其中使用某些非对称算法来加密随机生成的密钥,然后端点使用该密钥进行对称算法?只有在要加密的数据明显大于使用的密钥时,这种方法才有益处-这种情况是吗?请搜索PHP和RSA或ELGamal以获取非对称加密算法。 (请注意,如果您使用像GPG这样的东西来执行加密,可能会更快速和更容易进行编程- phpclasses上有包装器可用)。

使用GPG,完美地符合要求,而不必涉及加密技术。 - SimonJ
只要记得在某个地方备份密钥就好了 :) - SimonJ
最终,我只是想确保如果服务器被攻击,别人无法“解密”我的数据库中的数据(并且通过仅在本地存储唯一的“解密密钥”,我认为这至少是一个强有力的安全措施)。 - JM4

0

...这似乎是不可能的。MySQL的AES_DECRYPT方法需要编码后的消息以及原始密钥才能解密某些内容。这意味着任何可以获得加密密钥的人都可以解密该消息。


这是正确的 - 在临时情况下,我可能使用自己的密钥在线解密,但我永远不想能够直接查看数据库并查看开放数据。 - JM4
如果我想使用密钥“foo”进行加密,那么PHP需要在某个地方使用AES_ENCRYPT($password,'foo')。这意味着任何具有读取加密控制文件访问权限的人都可以解密数据库。但是,如果他是唯一具有读取访问权限的人,则私钥存储位置并不重要。 - cwallenpoole
我假设加密是在服务器端进行的,因为他说他想使用AES。AES并不像你所建议的那样工作(https://dev59.com/BXVC5IYBdhLWcg3wfxU8)。 - cwallenpoole
@Christopher W. Allen-Poole:我了解AES的工作原理。您可以使用AES(对称加密)和会话密钥加密消息。然后,您可以使用RSA算法和公钥加密会话密钥。然后将两个密码文本块发送到另一端。唯一的解密方法是使用RSA和与用于加密的公钥相关联的私钥解密会话密钥。然后,您可以使用解密后的会话密钥使用AES解密数据。 - Andrew Cooper
1
@Christopher W. Allen-Poole:他确实要求AES。 他还询问了使用“公钥”的问题,因此我提供了解决方案。这种方式之美在于,他的所有网络和数据库服务器仅看到密文。数据从未以明文形式出现在这些系统上,因此服务器的妥协不会威胁到数据。 - Andrew Cooper
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接