在mysql查询中解密数据,就像使用aes\u decrypt一样

cwxwcias  于 2021-06-20  发布在  Mysql
关注(0)|答案(1)|浏览(340)

我有一些sql查询,我在其中选择靠近用户位置的行。使用aes\ U decrypt,我可以在查询内部执行以下操作:

AES_DECRYPT(lat, :key)

我需要查询中的解密值:
1订购
2在给定区域内划定入口
三。其他的查询也有类似的情况
一个查询的简短示例:

SELECT something,
(
    6371 * acos( cos( radians(".$userdatafromdbfetchedbefore['lat'].") ) * cos( radians( AES_DECRYPT(lat, :key) ) ) * cos( radians( AES_DECRYPT(lng, :key) ) - radians(".$userdatafromdbfetchedbefore['lng'].") ) + sin( radians(".$userdatafromdbfetchedbefore['lat'].") ) * sin(radians( AES_DECRYPT(lat, :key))) )
) AS distance
FROM 
    table
HAVING 
    distance <= ".$userdatafromdbfetchedbefore['maxrange']."
ORDER BY 
    e.orderdate 
DESC,
    distance  
ASC
LIMIT
    ".$start.", ".$offset."

我不能在不同的查询中选择所有的行并用php操作结果,这对于100k+行是非常不重要的,而用户附近的行可能只有~100。
对我来说保持位置数据的加密是非常重要的,直到现在我才开始我的项目,因为加密不安全。
现在我的问题是如何用新的php实现的lib做同样的事情?
我找不到一个可行的例子。我刚刚发现了一个盲索引的例子,如果你像存储的一样加密搜索项,你可以找到一个值,但这在我的情况下是没有帮助的,因为我需要得到的值,通过距离公式运行在同一个查询。

oxiaedzo

oxiaedzo1#

libnadium没有内置到mysql中,所以不能调用与 AES_ENCRYPT() 从mysql查询中获取所需的结果。
但是,另一种方法是使用类似CipherWeet的库,它提供可搜索的认证加密。在决定使用它之前,请确保您了解它的特性和局限性。

<?php
use ParagonIE\CipherSweet\CipherSweet;
use ParagonIE\CipherSweet\EncryptedRow;
use ParagonIE\CipherSweet\Transformation\AlphaCharactersOnly;
use ParagonIE\CipherSweet\Transformation\FirstCharacter;
use ParagonIE\CipherSweet\Transformation\Lowercase;
use ParagonIE\CipherSweet\Backend\FIPSCrypto;
use ParagonIE\CipherSweet\KeyProvider\StringProvider;

$provider = new StringProvider(
    // Example key, chosen randomly, hex-encoded:
    'a981d3894b5884f6965baea64a09bb5b4b59c10e857008fc814923cf2f2de558'
);
$engine = new CipherSweet($provider, new FIPSCrypto());

/**@var CipherSweet $engine */
$row = (new EncryptedRow($engine, 'contacts'))
    ->addTextField('first_name')
    ->addTextField('last_name')
    ->addFloatField('latitude')
    ->addFloatField('longitude');

// Notice the ->addRowTransform() method:
$row->addCompoundIndex(
    $row->createCompoundIndex(
        'contact_first_init_last_name',
        ['first_name', 'last_name'],
        64, // 64 bits = 8 bytes
        true
    )
        ->addTransform('first_name', new AlphaCharactersOnly())
        ->addTransform('first_name', new Lowercase())
        ->addTransform('first_name', new FirstCharacter())
        ->addTransform('last_name', new AlphaCharactersOnly())
        ->addTransform('last_name', new Lowercase())
);

$prepared = $row->prepareRowForStorage([
    'first_name' => 'Jane',
    'last_name' => 'Doe',
    'latitude' => 52.52,
    'longitude' => -33.106,
    'extraneous' => true
]);

var_dump($prepared);

你应该看到类似的东西。中的值 [0] 会改变,但是 [1] 不会的。这是因为 [0] 包含行数据(某些字段已加密)。 [1] 仅包含盲索引(稍后可在选择查询中使用)。

array(2) {
  [0]=>
  array(5) {
    ["first_name"]=>
    string(141) "fips:nrtzoaxvPIOA7jPskWVwJmC0q8WJqrsnqjPh3ifNPsRd2TAx6OwTDfSiMVCXSsSRNQb_nxJlW7TbAtf5UvQRWWKTGhk_kXxpZKdnTrpjbmxi0IgstSrZ126Qz6E0_lvjew0Ygw=="
    ["last_name"]=>
    string(137) "fips:98f5CLB24w0zSqCGPR0D2oq9wQvUwzxo_byAp6mKgMgoJkUHZX1oTtk4Cm8FXI7fsUI8HOG5sKQFGRn6cXMw1EOMGgpXZqiXEDb3jxEbg9s95d4g2NeVd4xs2tmX0xlZ0nSM"
    ["latitude"]=>
    string(145) "fips:d3TVGfnRFlvWxbfihgHqjpXlXU3HtkCAHzM0-4f1l5dAeQf2Vk5RDDVOGMQNM09r0O4UOAub6QTyHGezQ0bWKQ5omqoYCTBJE0Uf_2DSPfO7U4dG74phaP04iFgqpJ8G41q54Kv5t54="
    ["longitude"]=>
    string(145) "fips:IcnUnBZZOxJPYXk-F3v12O_krNb9JsexljiV4gJzgctTpxLFm7ql0tJRF7xP3wLrUtd1VyfYBf75ot7iOSIIIFqsuyKZQdI9UyKbqd87RTMsHbHgPouxgZBg1urlqpuWqbOYEFGiti4="
    ["extraneous"]=>
    bool(true)
  }
  [1]=>
  array(1) {
    ["contact_first_init_last_name"]=>
    array(2) {
      ["type"]=>
      string(13) "w6dsrxbathjze"
      ["value"]=>
      string(16) "546b1ffd1f83c37a"
    }
  }
}

请注意,浮点字段将始终生成固定长度的输出,即使输入具有不同的精度级别。这样做是为了防止攻击者从密文长度中学习信息。
如果您选择 ModernCrypto 而不是 FIPSCrypto ,以上所有操作都将使用锂钠完成。如果有人好奇的话,这里会记录每个人使用的确切加密方法。
请注意,您必须用php而不是sql来计算解密后的值。
毕竟,在将数据存储到数据库之前对其进行加密的关键是对数据库服务器(以及任何可能危害该服务器的攻击者)隐藏数据。

相关问题