我正在创建一个 CakePHP 网络应用程序。显然密码是用散列存储的,但是有没有办法安全地存储将要检索的其他字段的值?我说的不是像信用卡一样敏感的东西,但 SSN 和薪水会被存储。我不确定存储此类信息的标准是什么,或者 CakePHP 是否有帮助程序。我使用 InnoDB 作为引擎。
最佳答案
I'm not talking anything as sensitive as credit cards, but SSN's and Salaries would be stored.
CakePHP 可能不直接支持这一点,但如果您使用 CipherSweet ,您不仅可以在存储敏感信息之前对其进行加密,而且仍然可以在您的 SELECT 查询中(间接地)使用这些字段。
例如,您可以加密用户的 SSN 和薪水,然后维护以下的独立索引:
- 用户的 SSN
- 用户 SSN 的最后 4 位数字
- 用户的工资
此外,CipherSweet 专门使用 authenticated encryption 并且密文是 securely randomized 。在引擎盖下,它 goes out of its way to ensure each field and index has a unique 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
和 Bob 的ssn_last4_idx
是相同的(bb0c
用于此 key ),因为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"]
你只会得到 Bob。同样:
"SELECT * FROM users WHERE ssn_idx = ?"
["3cc637b3"]
...将唯一标识爱丽丝。
长话短说
实现 searchable encryption 是一项艰巨的任务,但无需重新发明轮子。
CipherSweet 没有内置到 CakePHP 中,但没有理由不建议在未来的版本中包含它。
关于php - 在 mySQL 数据库中安全地存储值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18927735/