在mySQL数据库中安全地存储值

时间:2013-09-21 00:37:08

标签: php mysql security cakephp innodb

我正在创建一个CakePHP Web应用程序。显然密码是用哈希存储的,但有没有办法安全地存储将被检索的其他字段的值?我不是在说任何像信用卡一样敏感的东西,而是存储SSN和工资。我不确定存储信息的标准是什么,或者CakePHP是否有帮助。我使用InnoDB作为引擎。

1 个答案:

答案 0 :(得分:0)

  

我说的不是敏感的事情,但会存储SSN和薪金。

CakePHP可能不直接支持此功能,但是如果您使用CipherSweet,则不仅可以在存储敏感信息之前对其进行加密,还可以在SELECT查询中(间接)使用这些字段。

例如,您可以加密用户的SSN和薪水,然后维护以下各项的独立索引:

  • 用户的SSN
  • 用户的SSN的后4位数字
  • 用户的工资

此外,Cip​​herSweet仅使用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
        )
    )
;

加密和选择

密文是随机的,但索引是静态的。让我们加密用户的记录(我们称她为爱丽丝)。

$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),因为应用了LastFourDigits变换。
  • Alice和Bob的SSN和薪水不同,因此,他们的文字索引(ssn_idxsalary_idx)也不同。

因此,如果您选择的查询如下所示:

"SELECT * FROM users WHERE ssn_last4_idx = ?"
["bb0c"]

...您将获得两行(一列给爱丽丝,一列给鲍勃),因为它们的SSN的后4位相同。

但是,如果要使用它,则改为:

"SELECT * FROM users WHERE ssn_last4_idx = ? AND salary_idx = ?"
["bb0c", "0287"]

您只会得到Bob。同样:

"SELECT * FROM users WHERE ssn_idx = ?"
["3cc637b3"]

...将唯一标识爱丽丝。

TL; DR

实施searchable encryption是一项艰巨的任务,但无需重新发明轮子。

CakePHP并未内置CipherSweet,但是没有理由不能在以后的版本中提出。