How to encrypt large files in laravel

Time:2022-6-18

I have searched the software package or solution used to solve this problem, and encountered the stack overflow answer and the PHP solution, which is basically the PHP implementation of the solution described by stack overflow.

I decided to create an extension package designed for laravel to provide simple file encryption / decryption using simple and elegant syntax.

In this tutorial, I will describe in detail all the steps required to encrypt large files.

First, use the laravel installer to create a new laravel project named security app:

laravel new security-app

At the time of writing this tutorial, I was using laravel v6.5.2.

Because we have used the laravel installer, we have generated an application key and added it to our Env file. If you use other installation methods, do not forget to use the following methods to generate a new application key:

php artisan key:generate

Because we are using laravel Valet, we should have created a security app for us Test domain name. If you use another development environment, you should add a local domain name to point to the new project.

Since the front-end scaffolding has been moved to the laravel UI since laravel 6, we will install the laravel/ui extension package.

composer require laravel/ui — dev

Next, we will install the bootstrap and auth scaffolding:

php artisan ui bootstrap –auth

And compile everything:

npm install && npm run dev

We also need to be in Configure the database access credentials in the env file and run the initial migration:

php artisan migrate

Now we can create a new user and log in to view the user dashboard.

Note: in this demonstration, we will create a basic upload form, but in your application, you should consider using more complex upload functions to upload large files in blocks.

A very good extension package you can use is pion/laravel-chunk-upload

The laravel auth scaffold creates a /home route, a homecontroller and a home blade. PHP view file.

Let’s edit home blade. PHP file and add a form and an upload field:


<form action="{{ route('uploadFile') }}" method="post" enctype="multipart/form-data">
    @csrf
 
    <div>
        <div>
            <input type="file" name="userFile">
            <label for="userFile">Choose a file</label>
        </div>
    </div>
 
    <button type="submit">Upload</button>
 
    @if (session()->has('message'))
        <div>
            {{ session('message') }}
        </div>
    @endif
</form>

Then add the corresponding route:


Route::post(‘/home', ‘[email protected]')->name(‘uploadFile');

Add a store method in the homecontroller. This method stores the uploaded files in the file directory with the current user ID (storage/app/files/{user id}).

Note: This is incorrect and should not be used in a production environment. To make this tutorial smaller, we use the file system to get users’ files, but in the production environment, we need to use a database to track the files uploaded by each user.


<?php
   /**
     * Store a user uploaded file
     *
     * @param  \Illuminate\Http\Request $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        if ($request->hasFile('userFile') && $request->file('userFile')->isValid()) {
            Storage::putFile('files/' . auth()->user()->id, $request->file('userFile'));
        }
 
        return redirect()->route('home')->with('message', 'Upload complete');
    }

It’s time to encrypt the files uploaded by users. We will install the file vault expansion pack:

composer require soarecostin/file-vault

The package allows access to the filevault facade, which provides methods for encrypting and decrypting files, as well as methods for setting options, such as setting a different encryption key for each file, or specifying the laravel file system disk for the file.

We will use the filevault:: encrypt ($file) method to encrypt files uploaded by users. This function will delete the original unencrypted file and replace it with the same name and additional File with enc extension.

If you want to name the file with a different name, you can pass the desired name as the second parameter to the encrypt method. If you want to keep the original file, you can use the encryptcopy method.

This is what our store method looks like now:


<?php
    /**
     * Store a user uploaded file
     *
     * @param  \Illuminate\Http\Request $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        if ($request->hasFile('userFile') && $request->file('userFile')->isValid()) {
            $filename = Storage::putFile('files/' . auth()->user()->id, $request->file('userFile'));
 
            // Check to see if we have a valid file uploaded
            if ($filename) {
                FileVault::encrypt($filename);
            }
        }
 
        return redirect()->route('home')->with('message', 'Upload complete');
    }

Next, we need to view the files uploaded by all users and a way to download them.

We will create a new downloadfile route and a new downloadfile method in the homecontroller:


Route::get(‘/files/{filename}', ‘[email protected]')->name(‘downloadFile');

<?php
    /**
     * Download a file
     *
     * @param  string  $filename
     * @return \Illuminate\Http\Response
     */
    public function downloadFile($filename)
    {
        // Basic validation to check if the file exists and is in the user directory
        if (!Storage::has('files/' . auth()->user()->id . '/' . $filename)) {
            abort(404);
        }
 
        return response()->streamDownload(function () use ($filename) {
            FileVault::streamDecrypt('files/' . auth()->user()->id . '/' . $filename);
        }, Str::replaceLast('.enc', '', $filename));
    }

Downloadfile uses the native streamdownload response of laravel to receive a callback

In the callback, we are calling the streamdecrypt method provided by the extension package filevault, which will decrypt the file and provide it to the streamdownload method segment by segment, thus allowing your users to download the decrypted file directly.

Now, we need to display all users’ files below the upload form. To do this, we send the $files variable from the index method of homecontroller to home blade. PHP view file and display the user file below the upload table.


<?php
 
    /**
     * Show the application dashboard.
     *
     * @return \Illuminate\Contracts\Support\Renderable
     */
    public function index()
    {
        $files = Storage::files('files/' . auth()->user()->id);
 
        return view('home', compact('files'));
    }

home.blade.php


<ul>
    @forelse ($files as $file)
        <li>
            <a href="{{ route('downloadFile', basename($file)) }}" rel="external nofollow" >
                {{ basename($file) }}
            </a>
        </li>
    @empty
        <li>You have no files</li>
    @endforelse
</ul>

this is it! We are now using static encryption! We created forms for users to upload files, encrypted them, and decrypted them only when requested by the user who uploaded them.

Of course, in production, more security measures need to be taken, and the filevault expansion pack is designed to help you in this regard.

For example, you may want to store large files uploaded by users in Amazon S3, which supports file encryption / stream decryption.

You may also want to use a different encryption key for each user or file, which is also possible for the filevault expansion pack.

The above is a brief talk on how to encrypt large files in laravel. For more information on how to encrypt large files in laravel, please pay attention to other developeppaer related articles!

Recommended Today

Record the installation process of NVIDIA driver and NVIDIA container toolkits once

background You need to install the corresponding driver on the workstation equipped with NVIDIA geforce RTX 3060. To run Triton on the GPU, install NV container Toolkits step 1、 Check the model of the local graphics card on the NV official website https://www.nvidia.com/Download/index.aspx?lang=en-us Driver information queried Directly execute after downloading. After execution, run NVIDIA SMI […]