【问题标题】:Encrypt with PHP Mcrypt and Decrypt with MySQL aes_decrypt?用 PHP Mcrypt 加密和用 MySQL aes_decrypt 解密?
【发布时间】:2013-04-14 19:37:49
【问题描述】:

是否可以使用 PHP mcrypt 加密数据并使用 MySQL AES_DECRYPT 在数据库中解密?目前,我在 PHP 上将RIJNDAEL_128 用于mcrypt。我还确保数据库中的加密字段具有数据类型blob。然而,具有正确密钥的AES_DECRYPT 仍会返回NULL。关于如何让它发挥作用的任何建议?

【问题讨论】:

    标签: php mysql encryption aes rijndael


    【解决方案1】:

    如果您希望您的解决方案可扩展到许多用户,那么在搜索期间解密数据库中的数据似乎是个问题。

    我建议您查找旧宝石“绽放过滤器”。它通常用于拼写检查器,但也可用于加速数据库中的搜索。 https://en.wikipedia.org/wiki/Bloom_filter

    布隆过滤器是一个位掩码。您需要创建一系列不同的散列函数,这些函数生成的散列大小与布隆过滤器相同,但每个散列函数只设置一个随机位。

    然后您通过这些散列函数运行一个单词(字符串)并将这些位添加到您的过滤器中。现在过滤器“知道”你的话。

    过滤器很紧凑,因为单词可以在过滤器中相互重叠。

    要检查一个词是否在过滤器中,您只需对其运行散列函数并检查是否所有位都在过滤器中设置了二进制 AND 操作。 MySQL 支持二进制操作。

    您永远不能从过滤器中删除一个单词,因为这些位可以是多个单词的一部分。

    文本永远无法从布隆过滤器中恢复

    布隆过滤器永远不会给出误报,但它可能会给出误报。如果您得到误报,那么您的过滤器与您的数据集(存储在过滤器中的单词)相比太小,或者您的散列函数不够好。 需要多少个哈希函数取决于数据的大小,试试 5-20。

    提示!您还可以在布隆过滤器中添加成对的词或词的三元组。

    【讨论】:

      【解决方案2】:

      我找到了一些很好的帮助here

      请注意,这适用于纯文本中最多 65519 个字符的加密文本。(如果没有 UTF-8 编码,可能会更多)

      要加密的 PHP 代码:

      // MySQL uses 16 bytes key for 128 encryption/decryption
      $key = "ABCDEF0123456789";
      
      $plaintext = "This string was AES-128 / EBC / ZeroBytePadding encrypted.";
      // Optionally UTF-8 encode
      $plaintext_utf8 = utf8_encode($plaintext);
      // Find out what's your padding
      $pad_len = 16 - (strlen($plaintext_utf8) % 16);
      // Padd your text
      $plaintext_utf8 = str_pad($plaintext_utf8, (16 * (floor(strlen($plaintext_utf8) / 16) + 1)), chr($pad_len));
      
      // Encryption
      mt_srand();
      $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
      mcrypt_generic_init($td, $key, false);
      // Generates a warning about empty IV but it's Ok
      $ciphertext = mcrypt_generic($td, $plaintext_utf8);
      mcrypt_generic_deinit($td);
      $ciphertext = mysql_real_escape_string($ciphertext);
      
      // Store in MySQL
      $mysqli = new mysqli("localhost", "test", "test", "test");
      $mysqli->set_charset("utf8");
      $mysqli->query("insert into test(content) value ('$ciphertext')");
      $mysqli->close();
      

      用于搜索string was的SQL查询:

      SELECT CAST(AES_DECRYPT(content,'ABCDEF0123456789') AS CHAR) AS content
      FROM test
      WHERE CAST(AES_DECRYPT(content,'ABCDEF0123456789') AS CHAR) like '%string was%';
      

      输出是:

      This string was AES-128 / EBC / ZeroBytePadding encrypted.
      

      注意:MySQL 表的创建者:

      create table test (
      id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
      content blob ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
      

      【讨论】:

        【解决方案3】:

        如果您在 PHP 端使用 mcrypt RIJNDAEL_128 进行加密,那么我建议您在 PHP 端进行解密。不久前,当涉及到我的一个申请的学生证号码时,我也遇到了同样的问题。我选择反对让数据库进行任何类型的加密/解密。我强烈建议将其留给一个系统(在本例中为 mcrypt)。原因是现在你有更少的“移动”部件,这些部件可能会出错,从而更容易维护,并且更容易记录audit trails。您的数据库应该用于存储数据(不足为奇),因此只需确保数据库中的长度适合您所存储的内容。

        希望这能回答您的问题/以某种方式帮助您,因为这就是我将这样做/实际上正在这样做的方式。

        现在,如果您需要查看一些有关其工作原理的代码,请询问。根据我的理解,尽管我认为您知道如何进行加密/解密,但您只是在询问数据库是否应该解密信息。

        【讨论】:

        • 我使用 PHP mcrypt 解密用于大多数意图和目的,但我需要 SQL 来解密它,以便我可以创建一个搜索函数并在表中搜索与某个字符串匹配的行(该列将必须先解密 MYSQL 才能匹配它)。
        • 我想我不明白,先生,我很抱歉,但是如果您需要这种功能,那么如果您需要在数据库中解密值,为什么要首先加密?我只是想进一步了解您的问题。
        • 不用道歉,没有提供额外信息是我的错。我正在做一个笔记网站,我正在加密他们的所有数据以增加安全性。问题是我需要创建一个搜索功能,以便用户可以搜索他们的笔记,而目前唯一可行的方法是单独获取所有笔记行,用 php 解密,然后检查它,即在我看来远没有效率。所以我想知道如何简单地用 MySQL 解密它,然后像往常一样使用like 搜索。
        • 啊,嗯..如果可能的话,我能否提出另一种方法来做到这一点? (你可能已经想到了,但是......)如果你想让人们检查他们所有的特定笔记(用户 x 所做的那些),那么在我的思考过程中检索用户 x 的所有笔记,然后带来什么笔记从查询返回(来自用户 x 的查询)然后解密它们。
        • 这些天你会对 mysql 的处理能力感到惊讶。目前,我的数据库中有数千条记录,用于我为学校构建的应用程序、报告、动态查询、加密和解密电子邮件以发送给学生(根据制作的动态报告一次数百条),所有这些都可以处理,无需出汗。但这是我的建议。希望一切顺利!
        猜你喜欢
        • 2015-11-10
        • 2011-01-24
        • 2011-08-11
        • 2014-02-24
        • 2013-08-13
        • 2011-10-13
        • 2011-06-20
        • 2013-12-28
        • 2015-09-04
        相关资源
        最近更新 更多