kitlabs/kit-crypt-bundle
KitLabs Kit Crypt Bundle is a lightweight PHP encryption package for Laravel and PHP apps, offering simple, configurable helpers to securely encrypt and decrypt sensitive data. It provides reusable cryptographic utilities with minimal setup and straightforward integration.
Reality check before you type composer require: this is a Symfony bundle, not a Laravel package. It ships a Bundle subclass, a DI Extension with a Configuration tree, and YAML service definitions. Laravel has no equivalent lifecycle. There is no "install and autowire" path — plan for the integration cost up front rather than discovering it mid-sprint.
The minimum path to see it working:
composer.json almost certainly declares php: >=5.5 and symfony/*: ^2.8|^3.0. Against a Laravel 10/11/12 app on PHP 8.2+, expect constraint conflicts. Try composer require kitlabs/kit-crypt-bundle --dry-run first. If it blocks, stop — do not start rewriting constraints to force it in.openssl_* (and likely phpseclib for RSA/DSA/IDEA). Read its concrete class, not the bundle's extension. That class is what you would instantiate directly, bypassing Symfony entirely.Configuration tree. It defines the "keys and ciphers" config shape. Copy the shape into config/ for your adapter, but do not expose cipher choice to application config (see Gotchas).openssl.cnf. Run a one-line probe for the specific cipher you need before writing anything else.Your first real use case is almost certainly "decrypt legacy data during a migration," not "protect new data." If the requirement is protecting new data, close the tab and use Crypt::encryptString() (AES-256-GCM, keyed from APP_KEY) or sodium_crypto_secretbox. This package is a bridge to old formats, not a foundation.
Where to look first:
DependencyInjection/Extension and Configuration — to understand the config contract.openssl_encrypt/openssl_decrypt or hand-rolls primitives (if it hand-rolls, walk away).Do not consume the bundle. Extract the underlying service class into app/Support/Crypto/LegacyCipher.php, own it in your repo, and wire it via a plain Laravel ServiceProvider. This removes the Symfony kernel/DI dependency, gives you a code path you can audit, and makes it obvious to the next engineer that this is a scoped adapter.
// app/Providers/LegacyCryptoServiceProvider.php
public function register(): void
{
$this->app->singleton(LegacyCipherAdapter::class, fn () => new LegacyCipherAdapter(
cipher: 'des-ede3-cbc', // hard-coded; NOT from config
key: config('services.legacy.key'),
iv: null, // adapter generates per-message
));
}
Never let controllers or jobs talk to the cipher class directly. Define a domain interface so the eventual swap-out is a one-file change:
interface Encryptor
{
public function encrypt(string $plaintext): string; // modern path only
public function decrypt(string $ciphertext): string; // legacy path, deprecated
}
Then have two implementations: AesGcmEncryptor (default, new data) and LegacyDesEncryptor (marked @deprecated at creation, deleted when backfill completes). Inject the interface; bind the implementation in the provider.
The package almost certainly returns bare ciphertext with no IV, no key ID, no auth tag. Whatever you build around it must add an envelope. Even for the legacy adapter, wrap decrypt output in a version-tagged structure so you can identify legacy rows:
// New rows written by the modern path always start with a version byte
// v1:AES-GCM:keyId:<base64(nonce||tag||ct)>
// legacy rows are bare — detect by absence of prefix
The only sane endgame is deleting the legacy adapter. Write a queued job that reads a row with LegacyDesEncryptor::decrypt(), writes with AesGcmEncryptor::encrypt(), and updates in one transaction. Tag the column (or add a cipher_version column) so the job is idempotent and can be resumed. This is the actual deliverable — the adapter is a means to it.
use KitLabs\... outside app/Support/Crypto/.AppServiceProvider::boot(), probe openssl_get_cipher_methods() for the cipher you need and throw if it's missing. A silent fallback to a null cipher is the worst possible failure mode.mcrypt was removed in PHP 7.2. If the code paths for DES/RC2/RC4 depend on it, they are dead on any modern runtime. Verify the actual openssl_* call sites — if you find mcrypt_*, the package is abandoned pre-2017 and you should stop.openssl.cnf per host. Local Docker, CI, and production AMIs will disagree. Pin the cipher and add a boot-time availability check — otherwise the first legacy decrypt succeeds on a developer laptop and fails in production at 2 a.m.Crypt (GCM on Laravel 10.x+) and that the legacy adapter returns a single, uniform error on any decrypt failure — never false, never partial plaintext.decrypt() returning false/empty is a silent-corruption trap. OpenSSL returns false on bad padding; many wrappers pass that through. Hard-fail with an exception, and never log the ciphertext or the key.cipher_version column/project field before you write the first row, not after.SECURITY.md, no CVE process. Any vulnerability you hit will be your patch to write. Fork and vendor it, or better, extract the ~150 lines you need and drop the dependency.Encryptor::encrypt/decrypt and the config-keys-per-cipher map. Neither is worth paying the Symfony-integration tax for. The real extension point is your own interface — build there.How can I help you explore Laravel packages today?