Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Ciphersweet Laravel Package

paragonie/ciphersweet

CipherSweet is a PHP library for fast, secure field-level encryption with searchable encrypted indexes. Designed for applications that need to protect sensitive data at rest while still supporting equality and range queries, with strong cryptography and clean integrations.

View on GitHub
Deep Wiki
Context7
v4.9.0

What's Changed

New Contributors

Full Changelog: https://github.com/paragonie/ciphersweet/compare/v4.8.0...v4.9.0

v4.8.0

New Feature: If you use a StaticBlindIndexKeyProvider interface for your Key Providers, you can now designate a specific "tenant" identifier to be static and used for Blind Index root key derivation. This works with EncryptedRow and EncryptedMultiRows.

What's Changed

New Contributors

Full Changelog: https://github.com/paragonie/ciphersweet/compare/v4.7.0...v4.8.0

v4.7.0

Enhanced AAD

  • Added a new AAD class, which allows users to bind an encrypted field to the contents of multiple plaintext fields. This class can be used in the same place where a field name or literal value was used previously.
  • EncryptedFile now accepts an optional AAD param, which binds the file's contents to the AAD value.
  • Improved test coverage.
  • EncryptedRow now allows you to automatically bind fields to their context (i.e. primary key).
  • EncryptedMultiRows now allows you to enable auto-binding mode, which ensures that all fields are explicitly bound (via the AAD parameter) to, at minimum, the database row primary key, table name, and field name.

Here's a quick example of the old API, then a diff to use the new AAD features:

<?php
use ParagonIE\CipherSweet\CipherSweet;
use ParagonIE\CipherSweet\EncryptedMultiRows;
/** [@var](https://github.com/var) CipherSweet $engine */

$multiRowEncryptor = new EncryptedMultiRows($engine);
$multiRowEncryptor
    ->addTextField('table1', 'field1')
    ->addIntegerField('table1', 'field2')
    ->addFloatField('table1', 'field3')
    ->addOptionalBooleanField('table1', 'field4')
    ->addTextField('table2', 'foo')
    ->addTextField('table3', 'bar');

$encrypted = $multiRowEncryptor->encryptManyRows([
  'table1' => ['field1' => 'hello world', 'field2' => 42, 'field3' => 3.1416],
  'table2' => ['id' => 3, 'foo' => 'joy'],
  'table3' => ['foo' => 'coy'],
]);

And here's how to easily enable to new features:


  $multiRowEncryptor = new EncryptedMultiRows($engine);
  $multiRowEncryptor
+     ->setAutoBindContext(true)
+     ->setPrimaryKeyColumn('table2', 'id')
      ->addTextField('table1', 'field1')

With this change, every encrypted field is explicitly cryptographically bound to its context (table name, field name) with no further action needed from the developer.

Additionally, table2 is cryptographically bound to its primary key (id). This has two consequences:

  1. You cannot copy ciphertexts between rows and decrypt successfully. This is a good thing.
  2. However, you must know the primary key when inserting new records, in order to provide it to CipherSweet.

That second point is the main reason why we are not enabling it by default. (Also, we'd kind of need to know your primary key naming convention, which we cannot know for everyone that uses this library.)

We will update the documentation as soon as possible.

v4.6.1
  • Allow constant_time_encoding v3
v3.4.1
v4.5.1

More helpful exception message on NULL values. See #95, #92, #93.

If you do not declare a field optional, it generally will not accept NULL as a value on encrypt. Boolean is the exception to this rule (for backwards compat).

However, non-optional fields (even booleans) must have a ciphertext on the decrypt path.

Encrypt:
  TYPE_BOOLEAN + (null) -> ciphertext
  TYPE_OPTIONAL_BOOLEAN + (null) -> ciphertext

Decrypt:
  TYPE_BOOLEAN + (null) -> TypeError
  TYPE_OPTIONAL_BOOLEAN + (null) -> null

Booleans are the weird ones, though.

Encrypt:
  TYPE_TEXT + (null) -> TypeError
  TYPE_OPTIONAL_TEXT + (null) -> null

Decrypt:
  TYPE_TEXT + (null) -> TypeError
  TYPE_OPTIONAL_BOOLEAN + (null) -> null

Every other type doesn't tolerate null implicitly. This behavior is because of a very early design decision with boolean types.

v4.5.0

What's Changed

  • #92 Explicit support for optional field types
  • #88 Support json field map templating

Full Changelog: https://github.com/paragonie/ciphersweet/compare/v4.4.0...v4.5.0

v4.3.0

New: FastCompoundIndex, FastBlindIndex

Too many users have tripped over the conservative defaults for blind indexing. To alleviate this, we are introducing two new classes in the public API:

  1. FastBlindIndex
  2. FastCompoundIndex

This will always use a fast hash; which will be more suitable for all but the absolute most sensitive data.

v3.4.0
  • Fix #80 (see #81)
v4.2.0
  • Fix #80 (#81)
    • Add new methods setPermitEmpty() and getPermitEmpty(() to toggle whether empty values are tolerable in encrypted rows.
v3.3.0
  • Add setActiveTenant() to EncryptedFile
v4.1.0
  • Add setActiveTenant() to EncryptedFile
v4.0.2
  • #74, #76 - Use the new #[\SensitiveParameter] attribute for PHP 8.2
  • Added tests generated from CipherSweet-JS to ensure interop
v4.0.1
  • Fix #73
  • Fix #72
  • Expanded unit tests to prevent regressions
v4.0.0
  • Requires PHP 8.1 or newer
  • CipherSweet v4 uses a strictly-typed API and cuts a modest amount of polyfill code for supporting older PHP versions
v3.2.1
  • Fix: Strictness mode wasn't being passed from EncryptedRow to EncryptedJsonField.
v3.2.0

New feature: EncryptedJsonField

If you're using a modern SQL database that supports JSON documents in each row (i.e. PostgreSQL with JSONB), this new feature allows you to encrypt a subset of a JSON document at rest.

<?php
use ParagonIE\CipherSweet\CipherSweet;
use ParagonIE\CipherSweet\EncryptedJsonField;
use ParagonIE\CipherSweet\EncryptedRow;
use ParagonIE\CipherSweet\JsonFieldMap;

/** [@var](https://github.com/var) CipherSweet $engine */

// Create a JSON Field Map
$map = (new JsonFieldMap())
    ->addTextField('name')
    ->addBooleanField('active')
    // You can describe a full path to an attribute of a JSON document by passing an array describing it:
    ->addIntegerField(['address', 0, 'zip_code'])
    ->addIntegerField('age');

// Instantiate the JSON field on an EncryptedRow:
$encRow = (new EncryptedRow($engine, 'table_name'))
    ->addJsonField('column', $map);

// You can also do this (if you want it in isolation):
$jsonField = EncryptedJsonField::create($engine, $map, 'table_name', 'column');

// Encrypt some data
$plaintext = [
    'user_id' => 3495,
    'extra' => 'foo bar baz ...',
    // This is the JSON column:
    'column' => [
        'active' => false,
        'name' => 'John Doe',
        'address' => [
            [
                'line1' => '1600 Pennsylvania Ave NW',
                'line2' => '',
                'city' => 'Washington',
                'state' => 'DC',
                'zip_code' => 20500
            ]
        ],
        'age' => 33
    ],
    'extraneous' => 1
];

$encrypted = $encRow->encryptRow($plaintext);
var_dump($encrypted);

This should produce output similar to this (albeit with different ciphertext):

array(4) {
  ["user_id"]=>
  int(3495)
  ["extra"]=>
  string(15) "foo bar baz ..."
  ["column"]=>
  string(499) "{"active":"brng:K9DpP-000NEi1NwRP78fFQ7-Z7PDTR1vWPzb2LfZWMvHELDIZRFjh5KjDnNxC7JXUBhuyg8cNllu","name":"brng:bs039aez6fF-jttL65ZDMKI-OQe-CfvYHhjEir3AHL
Smt9OhivZwy6SI7aMNRzmWQEWThXfICtxq3DVoPJNuAw==","address":[{"line1":"1600 Pennsylvania Ave NW","line2":"","city":"Washington","state":"DC","zip_code":"brng:0CwKzWzj
HhCNS_1A0WLlZCnkv5iiTgP1cBUsHJuIMVLREJIef88eYFJR3RjB2j6_LEz7SiuONOKJXIxW9bYzdA=="}],"age":"brng:sIMNt1UG7FuyLGHQfS9FEsDv6HJuXRJaVeUyWUQ4GY15vZ_G21qJ2KadAMCc9VXcwMPG
OSQ89acrbCc6cRQJ1w=="}"
  ["extraneous"]=>
  int(1)
}

This serializes the encrypted JSON blobs as a string. During decryption, a string is expected as input, and it will return an array once decoded.

$decrypted = $encRow->decryptRow($encrypted);
var_dump($decrypted);

This will yield the following:

array(4) {
  ["user_id"]=>
  int(3495)
  ["extra"]=>
  string(15) "foo bar baz ..."
  ["column"]=>
  array(4) {
    ["active"]=>
    bool(false)
    ["name"]=>
    string(8) "John Doe"
    ["address"]=>
    array(1) {
      [0]=>
      array(5) {
        ["line1"]=>
        string(24) "1600 Pennsylvania Ave NW"
        ["line2"]=>
        string(0) ""
        ["city"]=>
        string(10) "Washington"
        ["state"]=>
        string(2) "DC"
        ["zip_code"]=>
        int(20500)
      }
    }
    ["age"]=>
    int(33)
  }
  ["extraneous"]=>
  int(1)
}
v3.1.0
  • Bugfix: The getTenant($name) method on the MultiTenantKeyProvider class incorrectly only returned the active tenant. This is fixed.
  • Added the getKeyProvider() method to CipherSweet. This is useful for calling methods on a multi-tenant-aware KeyProvider class (i.e. the parent one that wraps other KeyProvider classes).
v3.0.1
  • Handle NULLs more gracefully in EncryptedRow's decryption path. Fixes #62. (Thanks @lekoala!)
v3.0.0
  • Backwards Compatibility breaks
  • Introduce a variant of ModernCrypto called BoringCrypto which uses BLAKE2b-MAC instead of Poly1305.
    • BoringCrypto and FIPSCrypto are both suitable for use in multi-tenant data storage situations.
  • Added support for key providers that make multi-tenant setups possible.
  • See https://ciphersweet.paragonie.com for updated documentation.
v2.0.3
  • Fixes an issue with PHP 8
v2.0.2
  • Added PHP 8 to version constraint in composer.json
  • #52 - Prevent stream corruption when checking if a file is encrypted by specifying a rb flag.
  • #53 - Rewind streams after encrypting or decrypting.
  • #54 - New transformation (AlphaNumeric).
v2.0.1
v2.0.0

Backwards compatibility breaks!

CipherSweet v2.x is mostly but not completely backwards compatible with the v1.x branch. Many of the BC breaks were introduced by @mcordingley in #42:

  • I removed all mention of the back-end from the key provider. The key providers had no reason to know about the back-end in use, but its presence meant an additional method on the interface and somewhat more complicated instantiation logic. This change made the back-end a required parameter to the CipherSweet constructor, but the additional effort of providing it there is (more than) offset by no longer having to provide it to a key provider.
  • I removed getDefaultBackend(), as a change in the environment could cause a change in back-end, thereby rendering indexes and encrypted values "invalid". Different environments with the same code could nonetheless try to run different back-ends. :beetle:
  • I updated the CipherSweet constructor to make the back-end again an optional parameter. If not provided, we fall back to a default back-end. Unlike the removed factory method, this will always choose the same back-end implementation. Unless the user has specific reason otherwise, this is the back-end they will want. If the environment is unable to accommodate ModernCrypto, attempting to use it should throw an error and prompt either a code change or the installation of libsodium. Either way, the choice made will be explicit and intentional.

... snip ...

  • Removed ArrayProvider. It doesn't seem to add anything beyond what StringProvider already gives, but is less direct about it.

Additionally, some changes made by Paragon Initiative Enterprises to make the library easier to use and cleaner:

  • Invert the logic of "flat indexes" introduced in v1.10.0. The default are now "flat", and you can specify if you want typed indexes. This makes the default case slightly faster and simpler.
  • We now only support Psalm v3.x and disable these tests on PHP 7.0 and below.
v1.10.0

You can now call setFlatIndexes(true); if you don't need ["type" => "foo", "value" => "bar"] and only want "bar".

v1.9.0
  • New: EncryptedFile for encrypting files and PHP streams with authenticated encryption.
  • Fixed: #37 -- EncryptedRow::getBlindIndex() was not behaving as expected.
  • For anyone who wrote their own backend, the BackendInterface has several new methods added:
    • deriveKeyFromPassword(string $password, string $salt) should return a string.
    • doStreamEncrypt(resource $in, resource $out, SymmetricKey $key, int $chunkSize = 8192, string $salt = Constants::DUMMY_SALT) should return a boolean value.
    • doStreamDecrypt(resource $in, resource $out, SymmetricKey $key, int $chunkSize = 8192) should return a boolean value.
    • getFileEncryptionSaltOffset() should return an integer.
v1.8.0
  • Feature: API to make data migration between different backends or key providers seamless.
  • The BackendInterface interface now requires a method called getPrefix() that returns a string.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky