简体   繁体   English

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

[英]Storing values securely in mySQL Database

I am creating a CakePHP web application. 我正在创建一个CakePHP Web应用程序。 Obviously passwords are stored with a hash, but is there a way to securely store values of other fields that will be retrieved? 显然,密码是与哈希一起存储的,但是有没有办法安全地存储将要检索的其他字段的值? I'm not talking anything as sensitive as credit cards, but SSN's and Salaries would be stored. 我说的不是信用卡那样敏感的内容,但是会存储SSN和薪水。 I'm not sure what the standard for storing information such as this is, or if CakePHP has a helper for it. 我不确定存储诸如此类的信息的标准是什么,或者不知道CakePHP是否有它的帮助程序。 I am using InnoDB as the engine. 我正在使用InnoDB作为引擎。

I'm not talking anything as sensitive as credit cards, but SSN's and Salaries would be stored. 我说的不是信用卡那样敏感的内容,但是会存储SSN和薪水。

CakePHP might not directly support this, but if you use CipherSweet , you can not only encrypt sensitive information before storing it, but still use these fields (indirectly) in your SELECT queries. CakePHP可能不直接支持此功能,但是如果使用CipherSweet ,则不仅可以在存储敏感信息之前对其进行加密,还可以在SELECT查询中(间接)使用这些字段。

For example, you could encrypt the user's SSNs and salaries, and then maintain independent indexes of: 例如,您可以加密用户的SSN和薪水,然后维护以下各项的独立索引:

  • The user's SSN 用户的SSN
  • The last 4 digits of the user's SSN 用户的SSN的后4位数字
  • The user's salary 用户的薪水

Additionally, CipherSweet exclusively uses authenticated encryption and ciphertexts are securely randomized . 此外,Cip​​herSweet仅使用经过身份验证的加密,并且密文被安全地随机分配 Under the hood, it goes out of its way to ensure each field and index has a unique key . 在幕后,它竭力确保每个字段和索引都有唯一的键

CipherSweet Example CipherSweet示例

Setup 设定

<?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
        )
    )
;

Encrypting and SELECTing 加密和选择

Ciphertexts are randomized, but indexes are static. 密文是随机的,但索引是静态的。 Let's encrypt a user's records (let's call her 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);

This would produce something like: 这将产生如下内容:

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)
}

If you were to also compare this with another employee's records (let's call him Bob), you'd see similar indexes: 如果您还要将此数据与另一位员工的记录进行比较(我们称其为鲍勃),则会看到类似的索引:

$plaintext = [
    'username' => 'bob',
    'ssn' => '456-123-7890',
    'salary' => 135001
];

You would see something similar: 您会看到类似的内容:

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)
}

Some details worth noting: 一些细节值得注意:

  • Alice's ssn_last4_idx and Bob's ssn_last4_idx were identical ( bb0c for this key), because the LastFourDigits transform was applied. Alice的ssn_last4_idx和Bob的ssn_last4_idx是相同的( bb0c此键),因为LastFourDigits变换应用。
  • Alice and Bob's SSNs and salaries differed, and therefore, their literal indexes ( ssn_idx and salary_idx ) differed. 爱丽丝和鲍勃的SSN和薪水不同,因此,它们的文字索引( ssn_idxsalary_idx )也不同。

So if your select query looks like this: 因此,如果您的选择查询如下所示:

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

...you'll get two rows (one for Alice, one for Bob), since the last 4 digits of their SSNs are the same. ...您将获得两行(一列给爱丽丝,一列给鲍勃),因为它们的SSN的后4位相同。

But if you were to do use this instead: 但是,如果要使用它代替:

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

You'd only get Bob. 你只会得到鲍勃。 Similarly: 类似地:

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

...would uniquely identify Alice. ...将唯一地标识爱丽丝。

TL;DR TL; DR

Implementing searchable encryption is a nontrivial undertaking, but there's no need to reinvent the wheel. 实施可搜索的加密是一项艰巨的任务,但无需重新发明轮子。

CipherSweet isn't built into CakePHP, but there's no reason its inclusion couldn't be proposed in a future version. CipherSweet没有内置在CakePHP中,但是没有理由不能在将来的版本中提出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM