使用PHP在数据库中进行加密数据搜索

时间:2018-05-02 10:49:01

标签: php mysql

我有一个搜索功能,我正在升级以支持AES加密,对于我的生活,我不知道我做错了什么。

我通过搜索框传递相同的查询,就像我在数据库端加密数据之前所做的那样,并且我没有返回任何SQL错误。它每次只显示零结果。

加密前数据库的示例:

*****************************************************
* Firstname * Surname * Telephone * Email           *
*****************************************************
* Bob       * Smith   * 0193847   * bob@me.com      *
* Jane      * McBean  * 0584383   * jane@mail.com   *
*****************************************************

加密数据库示例:

*****************************************************
* Firstname * Surname * Telephone * Email           *
*****************************************************
* 2d1c5749  * 82559acc* fa3bc41c5 * 759d082559      *
* 13c5802a  * 070e76f8* 70e76f8fe * feaa0ac1635c    *
*****************************************************

以前的工作(非加密)版本:

if(isset($_POST["search"]) && strlen($_POST["search"]) > 3) {
$Search = filter_var($_POST["search"], FILTER_SANITIZE_STRING);
$Search = strip_tags($Search);
$Search_String = filter_var($_POST["search"], FILTER_SANITIZE_STRING);
$Search = "%$Search%";

    $Search_String = filter_var($Search_String, FILTER_SANITIZE_STRING);
            if(strlen(empty($Search_String))){ $error[] = 'The search string is empty';}

if(!isset($error)) {
$Search_list = $dbconn->prepare("SELECT sql_calc_found_rows
                                  event_candidate.id AS candidate_id,
                                  event_candidate.firstname,
                                  event_candidate.surname,
                                  event_candidate.telephone,
                                  event_candidate.email,
                                  FROM event_candidate
                                  WHERE CONCAT_WS(' ', event_candidate.firstname, event_candidate.surname, event_candidate.telephone, event_candidate.email) LIKE ?
                                  "); 
    $Search_list->execute(array($Search));

不返回任何内容的新代码:

    $Search = filter_var($_POST["search"], FILTER_SANITIZE_STRING);
    $Search = strip_tags($Search);
    $Search_String = filter_var($_POST["search"], FILTER_SANITIZE_STRING);
    $Search = "%".$Search."%";

$Search_list = $dbconn->prepare("SELECT sql_calc_found_rows
                              event_candidate_demo.id AS candidate_id,
                              event_candidate_demo.firstname,
                              event_candidate_demo.surname,
                              event_candidate_demo.telephone,
                              event_candidate_demo.email,
                              FROM event_candidate_demo
                              WHERE CONCAT_WS(' ', AES_DECRYPT(event_candidate_demo.firstname, UNHEX(:key)), AES_DECRYPT(event_candidate_demo.surname, UNHEX(:key)), AES_DECRYPT(event_candidate_demo.telephone, UNHEX(:key)), AES_DECRYPT(event_candidate_demo.email, UNHEX(:key))) LIKE ':search'
                              "); 
$Search_list->bindParam(':key', $Site_Key, PDO::PARAM_INT);
$Search_list->bindParam(':search', $Search, PDO::PARAM_STR);
$Search_list->execute();

因此,如果我搜索任何与Bob有关的内容,它会加载正确的记录,但是我对加密数据执行相同操作,并且它总是返回零结果。

我不确定是AES_DECRYPT导致问题还是切换到BindParam

2 个答案:

答案 0 :(得分:2)

加密时的数据变得类似于随机噪声。它也永远不会是相同的(如果你有不好的加密)

您的问题有两种解决方案:

  1. 从数据库中获取每一行,解密,比较。 < - 花了很多时间
  2. 存储哈希键,并比较哈希值。 < - 安全性降低,使猜测数据更容易
  3. 根据敏感度,速度和风险评估的需要,您必须选择两种邪恶中的一种。

    假设您使用选项2,您将拥有两个第一个名称列

    event_candidate.firstname,
    event_candidate.firstname_hash,
    

    firstname字段中存储加密名称 在firstname_hash中存储名字的哈希值

    您可以使用类似hash('sha512', strtolower($unencrypted_name))的内容来加密哈希值。

    然后从中选择数据,然后您可以

    $select = hash('sha512', strtolower($unencrypted_name));
    
    $Search_list->bindParam(':search', $select, PDO::PARAM_STR);
    

    但是,您只能进行完全匹配。整个名字需要匹配,额外的附带空间可能阻碍比赛。

    使用hmacs和其他方法可以更加安全地散列它。我提供的样本只是为了说明基本概念。您必须执行自己的风险分析和数据敏感性。

答案 1 :(得分:1)

使用" ... LIKE:搜索..."而不是" LIKE':搜索' ..."

您确定要正确检查PDO中的错误吗? 如果我运行你的例子,我得到一个错误"无效的参数号:绑定变量的数量与令牌的数量不匹配"而不是空的结果。 (这是因为':搜索'无法识别)

另一方面说明:如果你不知道你的两个变化中哪一个确实导致了这个问题,你为什么一开始就做两次变化呢?

(也许我应该把它写成评论,但我需要50个声誉才能发表评论。)