我正在创建一个 CakePHP Web 应用程序。显然密码是用散列存储的,但是有没有办法安全地存储将要检索的其他字段的值?我不是在谈论像信用卡一样敏感的东西,但会存储 SSN 和薪水。我不确定存储此类信息的标准是什么,或者 CakePHP 是否有帮助程序。我使用 InnoDB 作为引擎。
问问题
370 次
1 回答
0
我不是在谈论像信用卡一样敏感的东西,但会存储 SSN 和薪水。
CakePHP 可能不直接支持这一点,但如果您使用CipherSweet,您不仅可以在存储敏感信息之前对其进行加密,还可以在 SELECT 查询中(间接)使用这些字段。
例如,您可以加密用户的 SSN 和工资,然后维护以下独立索引:
- 用户的 SSN
- 用户 SSN 的后 4 位
- 用户工资
此外,CipherSweet 专门使用经过身份验证的加密,并且密文是安全随机的。在幕后,它竭尽全力确保每个字段和索引都有一个唯一的 key。
CipherSweet 示例
设置
<?php
use ParagonIE\CipherSweet\Backend\FIPSCrypto;
use ParagonIE\CipherSweet\BlindIndex;
use ParagonIE\CipherSweet\CipherSweet;
use ParagonIE\CipherSweet\EncryptedRow;
use ParagonIE\CipherSweet\KeyProvider\StringProvider;
use ParagonIE\CipherSweet\Transformation\LastFourDigits;
$cipher = new CipherSweet(
new StringProvider(
str_repeat("\xff", 32)
),
new FIPSCrypto()
);
$ER = (new EncryptedRow($cipher, 'users'))
->addIntegerField('salary')
->addTextField('ssn')
->addBlindIndex(
'ssn',
new BlindIndex('ssn_idx', [], 32)
)
->addBlindIndex(
'salary',
new BlindIndex('salary_idx', [], 16)
)
->addBlindIndex(
'ssn',
new BlindIndex(
'ssn_last4_idx',
[new LastFourDigits()],
16
)
)
;
加密和选择
密文是随机的,但索引是静态的。让我们加密一个用户的记录(我们称她为 Alice)。
$plaintext = [
'username' => 'alice',
'ssn' => '123-456-7890',
'salary' => 135000
];
list($row, $indexes) = $ER->prepareRowForStorage($plaintext);
$decrypted = $ER->decryptRow($row);
var_dump($row, $indexes, $decrypted);
这会产生类似的东西:
array(3) {
["username"]=>
string(5) "alice"
["ssn"]=>
string(149) "fips:sZU-A5GvF0vrXFTuXJMoIjKrr3HAO83dSsfPXajlTkg7-ce9goff4TGsbnsmBje77USijlEp3xR0sDTo2gekZEtzoDaoNUbBcm57Va5DiFztHEV2QaREEzCdU-uV5MOg3dpxoxfq116ZRlMA"
["salary"]=>
string(145) "fips:hoSB4beTtcMbOum2RoPYE8PSagvCDoeGq2mjiONm_mj6A_wobXxrMjb_x_Z-u7oMVg2TvpzXbxdN7JP0XGm6ITwefMMF5Jhq7rbYjAX38SWcCYcYyryHmBr5WgVFOJM-bvhuhAOEi6o="
}
array(3) {
["ssn_idx"]=>
string(8) "3cc637b3"
["ssn_last4_idx"]=>
string(4) "bb0c"
["salary_idx"]=>
string(4) "5879"
}
array(3) {
["username"]=>
string(5) "alice"
["ssn"]=>
string(12) "123-456-7890"
["salary"]=>
int(135000)
}
如果您还要将此与另一位员工的记录(我们称他为 Bob)进行比较,您会看到类似的索引:
$plaintext = [
'username' => 'bob',
'ssn' => '456-123-7890',
'salary' => 135001
];
你会看到类似的东西:
array(3) {
["username"]=>
string(3) "bob"
["ssn"]=>
string(149) "fips:yauOEc7jF529frr7BYf16N7WNDs0koRj5yX3RhyCVPacBWPr_G8KltBSjVkNobIu2sfeWeLFCRBr1p0VHoNCADd4PPcJa6IciKjU8-K5v7Znt93g-NNlhaMzPOLqE9UVob9YxKpMb-9ZEzcW"
["salary"]=>
string(145) "fips:X64DBCbralyoNuE2sZvK_HjkRhIdrnNbVY2qaHfM1s6YmMUjNnRHVS0mq_SYS3Vo982BL72RMumhtPLwa4MoewOD8ycgbLhRx74-CjyFXdqFbPkEoeLESCBu471O-19Dx-4JJVGROHM="
}
array(3) {
["ssn_idx"]=>
string(8) "6950e82d"
["ssn_last4_idx"]=>
string(4) "bb0c"
["salary_idx"]=>
string(4) "0287"
}
array(3) {
["username"]=>
string(3) "bob"
["ssn"]=>
string(12) "456-123-7890"
["salary"]=>
int(135001)
}
一些值得注意的细节:
- Alice
ssn_last4_idx
和 Bobssn_last4_idx
是相同的(bb0c
对于这个密钥),因为LastFourDigits
应用了转换。 - Alice 和 Bob 的 SSN 和薪水不同,因此他们的文字索引 (
ssn_idx
和salary_idx
) 不同。
因此,如果您的选择查询如下所示:
"SELECT * FROM users WHERE ssn_last4_idx = ?"
["bb0c"]
...你会得到两行(Alice 一个,Bob 一个),因为他们的 SSN 的最后 4 位是相同的。
但是,如果您要改用它:
"SELECT * FROM users WHERE ssn_last4_idx = ? AND salary_idx = ?"
["bb0c", "0287"]
你只会得到鲍勃。相似地:
"SELECT * FROM users WHERE ssn_idx = ?"
["3cc637b3"]
...将唯一标识爱丽丝。
TL;博士
实施可搜索加密是一项艰巨的任务,但没有必要重新发明轮子。
CipherSweet 没有内置到 CakePHP 中,但没有理由不能在未来的版本中提议将其包含在内。
于 2018-09-16T04:23:20.303 回答