问题描述
我正在使用 AWS KMS 为每个用户的会话生成唯一的密钥对,然后加密定义为使用开放 ssl 加密的每个列。因此,我实现了以下特征,在保存/检索时加密和解密 getEncryptAttributes
中定义的字段:
trait HasEncryption
{
/**
* Set the array of encrypted attributes which will be stored in the database as encrypted text. Ensure the database
* column type to be binary. If you know a precise size,set it like in the respective database migration linked below. Else,use laravel's builtin $table->binary()
* @return string[]
* @see \AddCipherKeyToUsers::up()
*/
abstract public function getEncryptAttributes(): array;
/**
* Init the model event-handlers
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public static function bootHasEncryption()
{
// On save: Encrypt the data and store the keys to decrypt in the database
static::saving(function (Model $model) {
// For all encrypt-attributes,encrypt the data
foreach ($model->getEncryptAttributes() as $attribute) {
if (!is_null($model->getAttribute($attribute))) {
$res = $model->encryptionService->encrypt($model->getAttribute($attribute));
$model->setAttribute($attribute,$res['encrypted']);
}
}
// If something was encrypted,store the encryption keys to the database to use for decryption
if (isset($res)) {
$model->setAttribute('encrypted_key',$res['key']);
$model->setAttribute('encryption_iv',$res['iv']);
}
return $model;
});
// On retreive: Decrypt all attributes using the keys stored above
static::retrieved(function (Model $model) {
// For all encrypt-attributes,decrypt the data with the encryption keys stored on encrypt method
foreach ($model->getEncryptAttributes() as $attribute) {
if (!is_null($model->getAttribute($attribute)) && !is_null($model->getAttribute('encrypted_key')) && !is_null($model->getAttribute('encryption_iv'))) {
$decrypted = $model->encryptionService->decrypt($model->getAttribute($attribute),$model->getAttribute('encrypted_key'),$model->getAttribute('encryption_iv'));
$model->setAttribute($attribute,$decrypted);
}
}
return $model;
});
}
/**
* Get the app's encryption service singelton through magic attribute accessor
*
* @return EncryptionService
*/
public function getEncryptionServiceAttribute(): EncryptionService
{
return app()->make(EncryptionService::class);
}
}
EncryptionService
是一个单例,它将在会话的生命周期内使用相同的键。如果会话中没有可用的密钥,它将连接到 AWS STS 并为此会话获取新令牌。
我们不能对 aurora 数据库使用默认的 AWS 加密,因为数据必须以加密状态通过网络,而且每个用户的数据都必须独立加密。
现在在实践中,加密和解密在存储某些东西时起作用,然后重新加载和读取数据。但是当我有这样的事情时:
$thing->setAttribute('encrypted_attribute','value');
$thing->save();
dump($thing->getAttribute('encrypted_attribute'); // will print ú©N╬B═Ø©ªx\rÒ┤Ò·&
saving
观察者显然会修改加密属性,但我只想加密实际进入数据库的内容,但保留本地状态。否则,例如多次保存时,它也会再次加密二进制数据,而不是使用实际属性。
有没有办法按照我的方向实现这一点,或者您是否建议采用完全不同的设计来实现部分加密的数据库?
编辑:有时,提出问题有助于我的大脑。我认为 eloquent 模型具有触发 finishSave
事件的 saved
方法。所以我在特征中添加了 static::saved
并在那里解密。似乎工作。不过,您是否发现此设计存在任何潜在缺陷,或者您是否体验过通常如何实现?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)