Weave 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

Kit Crypt Bundle Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

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:

  1. Verify it installs at all. The package predates PHP 8 and its 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.
  2. Find the actual cipher service. The valuable part is the class the bundle registers as its "crypt service" — a thin wrapper over 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.
  3. Read the 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).
  4. Confirm which ciphers actually run on your PHP/OpenSSL. DES, RC2, RC4, and 3DES are all in OpenSSL 3's legacy provider and may be unavailable depending on 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:

  • The bundle's DependencyInjection/Extension and Configuration — to understand the config contract.
  • Whatever class is aliased as the crypt service — to extract and re-use it directly.
  • The algorithm dispatch logic — to see whether it calls openssl_encrypt/openssl_decrypt or hand-rolls primitives (if it hand-rolls, walk away).

Implementation Patterns

Pattern 1 — Vendor and adapt (recommended if you adopt at all)

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

Pattern 2 — Wrap behind your own interface

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.

Pattern 3 — Envelope versioning from day one

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

Pattern 4 — Re-encryption backfill job

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.

Pattern 5 — Integration tips

  • Isolate the dependency. One adapter, one interface, one provider. No use KitLabs\... outside app/Support/Crypto/.
  • Fail fast at boot. On 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.
  • Treat DSA as a bug. It is listed as an "encryption" algorithm but is signature-only. If any path in the package treats it as encryption, do not call it.

Gotchas and Tips

  • 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 3.x legacy provider drift. DES/3DES/RC2/RC4/IDEA availability depends on 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.
  • No AEAD. Nothing in the algorithm inventory is AES-GCM/CCM/ChaCha20-Poly1305. Unauthenticated CBC decrypt with distinguishable error messages is a padding oracle waiting to happen. Ensure the modern path uses 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.
  • The ciphertext has no key ID. Rotation requires a hand-built dual-key read window and a full-table re-encrypt. Add a cipher_version column/project field before you write the first row, not after.
  • Do not expose cipher selection to config or to product. Configuration-driven cipher choice means a future config change silently changes ciphertext format. Hard-code the single legacy cipher and the single modern cipher.
  • The bundle is unmaintained — assume you are the maintainer. 5 stars, 0 dependents, no 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.
  • DSA is signature-only, mislabeled here as encryption. Any code that "encrypts" with DSA is broken by definition. This is a design smell that should raise your bar for auditing every other cipher path before trusting any of it.
  • Extension points you do get: 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.
  • The most common day-to-day use is a decrypt-only shim reading old rows. Budget the work as: triage requirement → read one cipher → adapter → backfill job → delete adapter. If you cannot name the date the adapter dies, do not ship it.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons