madmatt/silverstripe-encrypt-at-rest

启用数据库中数据的静态加密

安装次数: 6,330

依赖项: 1

建议者: 0

安全性: 0

星标: 7

关注者: 8

分支: 11

开放问题: 4

类型:silverstripe-vendormodule

2.0.0 2024-09-12 22:08 UTC

This package is auto-updated.

Last update: 2024-09-12 22:10:44 UTC


README

github actions

此模块允许在存储到数据库之前加密 Silverstripe CMS ORM 数据,并在应用中使用前自动解密。为此,我们使用只有 web 服务器才知道的密钥。

需要了解的注意事项

  • 需要注意的是,此模块并不能完全保证您数据的安全性。只有当您完全理解此模块的运作方式时,才应将其用作保护措施。在大多数情况下,加密整个数据库既充分又同样有效。只有当您的分层保护策略需要并允许时,才使用此模块来加密静态数据(逐字段加密)。明确来说,在加密静态数据时,必须在使用之前解密数据。在几乎所有情况下,托管网站的 web 服务器比数据库服务器更容易受到攻击,这意味着如果攻击者能够入侵您的 web 服务器,他们将能够访问数据库和用于加密数据的密钥。
  • 逐字段加密和解密数据会产生性能开销,可能会在项目中产生不良结果。
  • 此模块在底层使用 defuse/php-encryption 库,该库更重视安全性而不是性能。在 DataObject 上加密大量字段可能会显著降低读取或写入大量数据(例如 CMS 中的 ModelAdmin 视图,一次渲染 50+ 条记录)的操作速度(仅解密字段就可能需要几秒钟的处理时间)。应确保仅加密最少的数据集,并且这些数据不需要频繁使用。

要求

  • SilverStripe CMS 5.0

安装

通过 Composer 安装

composer require madmatt/silverstripe-encrypt-at-rest

安装完成后,您需要生成一个将用于加密所有数据的密钥。

  1. 使用 vendor/bin/generate-defuse-key 生成一个十六进制密钥(由 defuse/php-encryption 提供的工具)。这将输出一个以 def 开头的 ASCII 安全密钥。
  2. 将此密钥设置为环境变量 ENCRYPT_AT_REST_KEY

对于开发环境,您可以在 .env 中设置此变量,例如

ENCRYPT_AT_REST_KEY="{generated defuse key}"

有关更多信息,请参阅 SilverStripe 环境管理

使用方法

在您的 DataObject 中,使用加密字段类型创建新的数据库字段。注意:不支持将已包含数据的现有字段转换为加密字段。这可能 可能 会工作,但不能保证。您应该通过创建新字段并创建一个任务来映射旧字段到新加密字段(如果需要)来迁移您的数据。

例如

use Madmatt\EncryptAtRest\FieldType\EncryptedVarchar;

class SecureDataObject extends DataObject {

    private static $db = [
        'NormalText' => 'Varchar'
        'SecureText' => EncryptedVarchar::class
    ];

}

查看 src/FieldType 文件夹以获取所有字段类型,或查看以下列表

  • Madmatt\EncryptAtRest\FieldType\EncryptedDatetime
  • Madmatt\EncryptAtRest\FieldType\EncryptedDecimal
  • Madmatt\EncryptAtRest\FieldType\EncryptedEnum
  • Madmatt\EncryptAtRest\FieldType\EncryptedInt
  • Madmatt\EncryptAtRest\FieldType\EncryptedText
  • Madmatt\EncryptAtRest\FieldType\EncryptedVarchar

注意:在数据库中保存时,所有这些加密字段都存储为TEXT列类型。这是因为加密数据的长度通常比原始文本字符串长得多。它们不会占用表列空间,但当许多字段包含在内时,会导致查询执行时间更长,因为数据库需要从单独的blob存储中检索所有这些字段。

注意2:这些字段都扩展自基本数据类型(例如,EncryptedDatetime extends DBDatetime),因此大多数常见的字段辅助方法都可以使用(例如,$DatetimeField.Ago)。

当值写入数据库时,数据将自动加密,并且每当从数据库读取该数据时,它都会被解密。

要使用解密值,您只需像在其他任何上下文中一样使用该值即可。例如

// Via DataObject::get()
$obj = SecureDataObject::get()->first()->SecureText; // Returns the decrypted string from the field

// Getting the DB field
$obj = SecureDataObject::get()->first();
$field = $obj->dbObject('SecureText'); // Returns an EncryptedVarchar object
$uppercase = $field->UpperCase(); // Method on DBString, returns a string

在Silverstripe模板中的使用也非常简单

<% loop $SecureDataObjects %>
    <p>$SecureText.UpperCase</p>
<% end_loop %>

如果您已使用此模块的Silverstripe CMS 3版本,您就不再需要依赖->getDecryptedValue()方法——在访问时值始终会被解密。

在不使用ORM的情况下加密和解密任意文本字符串和文件

您还可以在不使用Silverstripe ORM的情况下加密/解密任意文本字符串以及整个文件系统上的整个文件(例如,不使用DataObject)。例如,您可能想这样做是为了安全地与API通信。

use Madmatt\EncryptAtRest\AtRestCryptoService;
use SilverStripe\Assets\File;
use SilverStripe\Core\Injector\Injector;

$text = 'This is an unencrypted string!';

/** @var AtRestCryptoService $service */
$service = Injector::inst()->get(AtRestCryptoService::class);
$encryptedText = $service->encrypt($text); // Returns encrypted string starting with `def`
$unencryptedText = $service->decrypt($encryptedText); // Returns 'This is an unencrypted string!'

$file = File::get()->byID(1); // Presume this is a file that contains the text string above

// This will encrypt the file contents, delete the original file from the filesystem and create a new file at the same path with .enc appended to the filename
$encryptedFile = $service->encryptFile($file);

// This will decrypt the file contents, delete the encrypted file from the filesystem and create a new file at the same path with .enc stripped from the filename
$decryptedFile = $service->decryptFile($encryptedFile);