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

Js Crypto Store Bundle Laravel Package

azine/js-crypto-store-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Bundle Add to composer.json:

    "require": {
        "azine/js-crypto-store-bundle": "dev-master"
    }
    

    Run:

    composer require azine/js-crypto-store-bundle
    
  2. Register the Bundle Add to config/bundles.php:

    return [
        // ...
        Azine\JsCryptoStoreBundle\AzineJsCryptoStoreBundle::class => ['all' => true],
    ];
    
  3. Configure Routes & Services Add to config/routes.yaml:

    azine_js_crypto_store:
        resource: "@AzineJsCryptoStoreBundle/Resources/config/routing.yml"
    
  4. Configure Encryption & Storage Add to config/packages/azine_js_crypto_store.yaml:

    azine_js_crypto_store:
        ownerProvider: Azine\JsCryptoStoreBundle\Service\DefaultOwnerProvider
        encryptionCipher: aes
        encryptionMode: gcm
        defaultLifeTime: '14 days'
        maxFileSize: 50000000
    
  5. Set Up Database & Filesystem Ensure your doctrine and framework configs include:

    • A filesystem adapter (e.g., local, aws, etc.) for encrypted file storage.
    • A database entity manager for metadata storage.
  6. First Use Case: Client-Side Upload Include the bundle’s JS library in your frontend:

    <script src="{{ asset('bundles/azinejscripstore/js/sjcl.min.js') }}"></script>
    <script src="{{ asset('bundles/azinejscripstore/js/js-crypto-store.js') }}"></script>
    

    Use the provided HTML form (or custom implementation) to upload encrypted files via the /upload endpoint.


Implementation Patterns

Workflow: Secure File Upload & Sharing

  1. Client-Side Encryption

    • Use sjcl (Stanford Javascript Crypto Library) to encrypt files in the browser before upload.
    • Example encryption logic (provided by the bundle):
      // Encrypt file using sjcl
      const encryptedData = sjcl.encrypt(
          password,
          fileContent,
          { ks: 256, iterations: 1000 }
      );
      
    • Send encrypted data + metadata (e.g., filename, expiry) to /upload.
  2. Server-Side Storage

    • The bundle stores:
      • Metadata (e.g., owner_id, expiry_date, file_hash) in the database.
      • Encrypted content as a file in the configured filesystem (e.g., uploads/encrypted/).
    • Example entity structure (auto-generated by the bundle):
      // src/Entity/EncryptedFile.php
      class EncryptedFile {
          // ...
          private $ownerId;
          private $filePath; // Path to encrypted file in filesystem
          private $expiryDate;
          private $metadata; // JSON-serialized (e.g., original filename)
      }
      
  3. Sharing Files

    • Generate shareable links via /share endpoint:
      // Controller example
      $file = $this->getDoctrine()->getRepository(EncryptedFile::class)->find($id);
      $shareLink = $this->generateUrl('azine_js_crypto_store_download', ['token' => $file->getShareToken()]);
      
    • Links include a token (e.g., UUID) and optional expiry.
  4. Download & Decryption

    • Client-side decryption occurs after download:
      // Decrypt using sjcl
      const decryptedData = sjcl.decrypt(password, encryptedData, { ks: 256 });
      
    • Use the /download endpoint with the share token.

Integration Tips

  1. Custom Owner Logic Extend OwnerProviderInterface to dynamically assign files to users/groups:

    // src/Service/CustomOwnerProvider.php
    class CustomOwnerProvider implements OwnerProviderInterface {
        public function getOwnerId(): int {
            // Logic to fetch owner (e.g., current user, team lead, etc.)
            return $this->userService->getCurrentUser()->getId();
        }
    }
    

    Register as a service in services.yaml:

    services:
        Azine\JsCryptoStoreBundle\Service\OwnerProviderInterface: '@App\Service\CustomOwnerProvider'
    
  2. Frontend Integration

    • Use the bundle’s Twig helpers for forms:
      {{ render(azine_js_crypto_store_upload_form()) }}
      
    • Customize the expiry date picker (e.g., Foundation Datepicker) as shown in the README.
  3. Cleanup Expired Files Schedule the azine:js-crypto-store:cleanup command via cron:

    php bin/console azine:js-crypto-store:cleanup
    

    Configure retention policies in config/packages/azine_js_crypto_store.yaml:

    azine_js_crypto_store:
        cleanup:
            dryRun: false  # Set to true for testing
            batchSize: 100
    
  4. Validation & Error Handling

    • Validate file sizes on the client and server:
      if (file.size > 50000000) {
          alert('File too large (max 50MB)');
      }
      
    • Handle encryption errors gracefully:
      try {
          $encryptedFile = $this->cryptoStore->upload($encryptedData, $metadata);
      } catch (EncryptionException $e) {
          // Log and notify user
      }
      

Gotchas and Tips

Pitfalls

  1. Encryption Key Management

    • Issue: The bundle relies on client-side encryption keys (passwords). Lost passwords = lost data.
    • Solution:
      • Implement a password recovery flow (e.g., store hashed passwords or use a key escrow system).
      • Warn users to never lose their encryption password.
  2. Filesystem Permissions

    • Issue: The bundle stores encrypted files in a local directory. Incorrect permissions can cause upload failures.
    • Solution:
      • Ensure the uploads/encrypted/ directory is writable by the web server:
        chmod -R 775 var/uploads/encrypted/
        chown -R www-data:www-data var/uploads/encrypted/
        
      • For production, use a dedicated filesystem adapter (e.g., S3) with proper IAM roles.
  3. Database Locking

    • Issue: Concurrent uploads/shares may cause race conditions on EncryptedFile entities.
    • Solution:
      • Use database transactions for critical operations:
        $entityManager->beginTransaction();
        try {
            $entityManager->persist($file);
            $entityManager->flush();
            $entityManager->commit();
        } catch (\Exception $e) {
            $entityManager->rollBack();
            throw $e;
        }
        
  4. Cipher Configuration

    • Issue: Incorrect encryptionCipher/encryptionMode settings may cause decryption failures.
    • Solution:
      • Stick to AES-GCM (default) for authenticated encryption.
      • Validate cipher compatibility with sjcl:
        // Test cipher support in browser
        console.log(sjcl.codec.utf8String.fromBits(sjcl.encrypt('test', 'data', { cipher: 'aes' })));
        
  5. Token Security

    • Issue: Share tokens (UUIDs) are predictable if not properly generated.
    • Solution:
      • Override the token generator to use a cryptographically secure method:
        // src/Service/CustomTokenGenerator.php
        class CustomTokenGenerator {
            public function generateToken(): string {
                return bin2hex(random_bytes(16)); // 128-bit UUID
            }
        }
        
      • Register as a service:
        services:
            Azine\JsCryptoStoreBundle\Service\TokenGeneratorInterface: '@App\Service\CustomTokenGenerator'
        

Debugging Tips

  1. Enable Verbose Logging Configure Monolog in config/packages/monolog.yaml:

    monolog:
        handlers:
            main:
                level: debug
                channels: ["!event"]
    

    Check logs for encryption/decryption errors:

    grep -i "crypto" var/log/dev.log
    
  2. Test Encryption Locally Use the bundle’s CLI tool to verify encryption/decryption:

    php bin/console azine:js-crypto-store:test-encryption
    
  3. Inspect Database Metadata Query the encrypted_file table to verify metadata:

    SELECT * FROM encrypted_file WHERE owner_id = 1;
    

    Check for:

    • file_path
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.
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium