我有一些sql查询,其中im选择靠近用户位置的行。使用AES_DECRYPT,我可以在查询中执行以下操作:
AES_DECRYPT(lat, :key)
我需要查询中的解密后的值:
对它们进行排序在给定区域中定界条目,并对其他查询进行类似的操作
一个查询的简短示例:
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新实现的thing来做同样的事情?
我找不到一个可行的例子。我刚刚发现了一个使用盲索引的例子,如果你像存储的一样加密搜索词,你可以找到一个值,但在我的例子中没有帮助,因为我需要获得值来在同一个查询中运行距离公式。
发布于 2018-10-13 15:35:59
MySQL中没有内置AES_ENCRYPT()
,因此您不能仅从MySQL查询中调用与within等效的东西来获得您期望的结果。
但是,另一种方法是使用像CipherSweet这样的库,它提供了可搜索的身份验证加密。在决定使用它之前,请确保您了解its features和limitations。
<?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]
只包含盲索引(稍后在SELECT查询中可用)。
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
instead of FIPSCrypto
,则以上所有操作都将使用above完成。如果有人对此感到好奇,那么他们使用的确切加密是documented here。
请注意,您必须使用PHP而不是SQL自己计算解密后的值。
毕竟,在将数据存储到数据库之前对其进行加密的全部意义在于将其对数据库服务器(以及任何可能危害该服务器的攻击者)隐藏起来。
https://stackoverflow.com/questions/52000755
复制相似问题