【问题标题】:PHP, MySQL, and AES Encryption / Decryption for User Data用户数据的 PHP、MySQL 和 AES 加密/解密
【发布时间】:2010-10-25 23:12:44
【问题描述】:

我是 AES 加密的新手,但我正在尝试构建一个解决方案:

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

我意识到这可能有点矫枉过正,但我​​想过度保护我的消费者数据。

需要注意的几点:

  1. 这不是信用卡信息 所以请不要写信告诉我 关于 PCI-DSS,它是另一种形式 个人信息全部低于 500 每个字段的长度字符。
  2. 我可以存储消费者的碎片 信息和其他在一秒钟内 由一个独特的数据库捆绑在一起 会员 ID 以提高安全性。
  3. 传入的 MySQL 调用只能是 直接从我的服务器上制作 静态 IP。
  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 文件数据的方法?

【问题讨论】:

    标签: php mysql encryption aes


    【解决方案1】:

    您应该能够在您的个人计算机上生成公钥/私钥对,然后在您的应用中发布公钥,以便对数据进行加密。这样,服务器永远不会看到私钥,如果服务器被黑客入侵,数据仍然是安全的。

    您需要确保整个事务通过 SSL 进行。客户端可以生成一个随机会话密钥,使用该密钥加密数据(使用 AES),然后使用您的应用程序中的公钥加密该密钥(使用 RSA),并将加密的数据和密钥发送到服务器。您可以将整个 blob 存储在一个或两个数据库字段中。解密数据的唯一方法是先解密密钥,而唯一的方法是使用您个人机器上的私钥。

    更新

    查看http://plugins.jquery.com/project/jQuery-Gibberish-AES。这是一个 JQuery 插件,似乎允许这种类型的场景。我没有使用它的经验,但在我看来这是一个好的开始。

    新更新

    只是为了清楚我的建议,并解决您的编辑:

    您不能只使用 AES 加密。对于 AES,有一个密钥用于加密和解密。密钥必须存在于加密操作发生的任何地方,无论是在客户端代码中,还是在 Web 服务器上。在第一种情况下,任何人都可以获得您的密钥。在第二种情况下,如果网络服务器受到威胁,那么密钥和数据也会面临风险。

    解决方案是将良好、强大的 AES 加密与公钥加密 (RSA) 结合使用。我建议在客户端对加密进行操作,原因我将在下面概述。不过,这里是我建议的步骤:

    1. 在您的私人机器上创建一个公钥/私钥对,并确保私钥安全。
    2. 将公钥放在发送给客户端的代码中。
    3. 当用户提交表单时客户端代码:
      1. 生成随机 AES 密钥(会话密钥)
      2. 加密表单数据
      3. 使用您的公钥和 RSA 算法来加密会话密钥
      4. 丢弃明文会话密钥
      5. 将加密的表单数据和加密的会话密钥发送到您的服务器
    4. 您的服务器接受加密的表单数据,并将其与加密的密钥一起存储在数据库中。

    您现在在数据库中拥有加密数据,这些数据只能使用存储在您的私人计算机上的私钥进行检索。即使用户设法在他的机器上明文的情况下捕获了会话密钥,最糟糕的情况是该记录可能被解密。

    我建议这种客户端方法的原因是它意味着您的服务器永远不会看到明文的加密密钥。如果在服务器端采用相同的方案,那么理论上,攻击者可能会坐在您的服务器上观看它的发生。归根结底,这基本上归结为您想成为多么偏执。

    按照此方案,当您想要检索数据时,您可以将所需数据以加密形式从数据库转储到您的私人计算机。对于每一块加密数据:

    1. 使用 RSA 算法和您的私钥解密会话密钥
    2. 使用 AES 和步骤 1 中的会话密钥解密数据。

    无论如何,这就是我建议的方法。我敢肯定有图书馆可以处理这个问题。

    【讨论】:

    • 我不确定它应该如何工作:AES_ENCRYPT 只能使用一个字符串和一个密钥进行加密。可以访问密钥的任何地方都可以访问密钥加密的 blob 中包含的任何内容。服务器如何在不访问该密钥的情况下加密某些内容?
    • @Christopher W. Allen-Poole - 您假设加密发生在服务器上。如果它发生在客户端,然后客户端发送加密数据和使用公钥加密的密钥,那么服务器上没有任何东西可以解密它。服务器不需要知道用于加密数据的会话密钥。
    • @Andrew Cooper - 我查看了乱七八糟的 jquery 代码,但似乎并不一定能按规定运行,而且“文档”很糟糕。我添加了一个新的编辑来进一步解释我的目标。
    • @JM4:就像我说的,我没有使用 Gibberish 的经验——我只是通过 Google 找到的。我敢肯定有一些工具可以帮助你。有关我建议的方法的更详细说明,请参阅我的更新。
    • @Andrew Cooper - 我已经开始采用你的方法,我最喜欢它。如果你有机会,介意看看我最近的编辑吗?
    【解决方案2】:

    使用 AES 和“公共”密钥加密该数据 ... 仅使用私钥解密数据

    但 AES 是一种对称加密算法 - 即加密和解密使用相同的密钥。

    或者你的意思是你想实现类似 SSL 的东西,其中一些不对称算法用于加密随机生成的密钥,然后端点使用该密钥进行对称算法?这种方法只有在要加密的数据明显大于所使用的密钥时才有用 - 是这种情况吗?

    有一个用于 PHP 和 RSA 的 google 或用于非对称加密算法的 ELGamal。 (请注意,如果您使用 GPG 之类的东西进行加密,它可能会更快更容易编程 - phpclasses 上有包装器)。

    C.

    【讨论】:

    • +1 用于使用 GPG,完全符合要求,无需弄脏加密货币。
    • 记得在某处备份密钥 :)
    • 最后,我只是想确保如果服务器受到破坏,有人无法“解密”我的数据库中的数据(并且通过将唯一的“解密密钥”存储在本地,我认为它至少是强大的安全措施)。
    【解决方案3】:

    ... 这并没有让我感到震惊。 MySQL 的 AES_DECRYPT 方法需要编码消息以及原始密钥才能解密某些内容。这意味着任何可以获得加密密钥的人都可以解密消息。

    【讨论】:

    • 但他不想解密。他想以加密形式将数据存储在数据库中。对吗@JM4?
    • 这是正确的 - 我可以在临时情况下使用自己的密钥在线解密,但我永远不想能够直接查看数据库并查看开放数据
    • 如果我尝试使用密钥“foo”进行加密,那么 PHP 需要在某处使用 AES_ENCRYPT($password, 'foo')。这意味着任何对控制加密的文件具有读取访问权限的人都可以解密数据库。但是,如果他是唯一具有读取权限的人,那么私钥在哪里就无关紧要了。
    • 答案是——不要在服务器上加密。在客户端对数据进行加密,并以加密形式与使用公钥加密的会话密钥一起发送到服务器(然后存储在数据库中)。解密数据的唯一方法是首先使用保留的私钥解密会话密钥,嗯,私有。
    • @Christopher W. Allen-Poole:他确实要求使用 AES。他还询问了使用“公钥”的问题,因此是我的解决方案。这样做的好处在于,他所有的 Web 和数据库服务器所看到的都是密文。在这些系统中的任何一个上,数据都永远不会“被清除”,因此服务器的入侵不会破坏数据。
    猜你喜欢
    • 2016-04-25
    • 1970-01-01
    • 2016-09-22
    • 1970-01-01
    • 2018-10-03
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 2015-01-20
    相关资源
    最近更新 更多