Protecting PDFs with a password | laravel-pdf | Spatie

 SPATIE

  Laravel PDF
==============

spatie.be/open-source

  [Docs](https://spatie.be/docs)  [Laravel-pdf](https://spatie.be/docs/laravel-pdf/v2)  Basic-usage  Protecting PDFs with a password

 Version   v2   v1

 Other versions for crawler [v2](https://spatie.be/docs/laravel-pdf/v2) [v1](https://spatie.be/docs/laravel-pdf/v1)

  Protecting PDFs with a password
- [ Introduction ](https://spatie.be/docs/laravel-pdf/v2/introduction)
- [ Support us ](https://spatie.be/docs/laravel-pdf/v2/support-us)
- [ Requirements ](https://spatie.be/docs/laravel-pdf/v2/requirements)
- [ Installation &amp; setup ](https://spatie.be/docs/laravel-pdf/v2/installation-setup)
- [ Questions and issues ](https://spatie.be/docs/laravel-pdf/v2/questions-issues)
- [ Alternatives ](https://spatie.be/docs/laravel-pdf/v2/alternatives)
- [ Changelog ](https://spatie.be/docs/laravel-pdf/v2/changelog)
- [ About us ](https://spatie.be/docs/laravel-pdf/v2/about-us)

Basic usage
-----------

- [ Creating PDFs ](https://spatie.be/docs/laravel-pdf/v2/basic-usage/creating-pdfs)
- [ Responding with PDFs ](https://spatie.be/docs/laravel-pdf/v2/basic-usage/responding-with-pdfs)
- [ Formatting PDFs ](https://spatie.be/docs/laravel-pdf/v2/basic-usage/formatting-pdfs)
- [ Saving PDFs to disks ](https://spatie.be/docs/laravel-pdf/v2/basic-usage/saving-pdfs-to-disks)
- [ Attaching PDFs to mails ](https://spatie.be/docs/laravel-pdf/v2/basic-usage/attaching-pdfs-to-mails)
- [ Queued PDF generation ](https://spatie.be/docs/laravel-pdf/v2/basic-usage/queued-pdf-generation)
- [ Testing PDFs ](https://spatie.be/docs/laravel-pdf/v2/basic-usage/testing-pdfs)
- [ Setting defaults ](https://spatie.be/docs/laravel-pdf/v2/basic-usage/setting-defaults)
- [ Protecting PDFs with a password ](https://spatie.be/docs/laravel-pdf/v2/basic-usage/protecting-pdfs-with-a-password)

Drivers
-------

- [ Configuration ](https://spatie.be/docs/laravel-pdf/v2/drivers/configuration)
- [ Customizing Browsershot ](https://spatie.be/docs/laravel-pdf/v2/drivers/customizing-browsershot)
- [ Using the Cloudflare driver ](https://spatie.be/docs/laravel-pdf/v2/drivers/using-the-cloudflare-driver)
- [ Using the DOMPDF driver ](https://spatie.be/docs/laravel-pdf/v2/drivers/using-the-dompdf-driver)
- [ Generating PDFs on AWS Lambda ](https://spatie.be/docs/laravel-pdf/v2/drivers/generating-pdfs-on-aws-lambda)
- [ Using the Chrome driver ](https://spatie.be/docs/laravel-pdf/v2/drivers/using-the-chrome-driver)
- [ Using the Gotenberg driver ](https://spatie.be/docs/laravel-pdf/v2/drivers/using-the-gotenberg-driver)
- [ Using the WeasyPrint driver ](https://spatie.be/docs/laravel-pdf/v2/drivers/using-the-weasyprint-driver)
- [ Custom drivers ](https://spatie.be/docs/laravel-pdf/v2/drivers/custom-drivers)

Advanced usage
--------------

- [ Creating PDFs with multiple pages ](https://spatie.be/docs/laravel-pdf/v2/advanced-usage/creating-pdfs-with-multiple-pages)
- [ Using Tailwind ](https://spatie.be/docs/laravel-pdf/v2/advanced-usage/using-tailwind)
- [ Extending with Macros ](https://spatie.be/docs/laravel-pdf/v2/advanced-usage/extending-with-macros)
- [ Waiting for readiness ](https://spatie.be/docs/laravel-pdf/v2/advanced-usage/waiting-for-readiness)
- [ Caching PDFs ](https://spatie.be/docs/laravel-pdf/v2/advanced-usage/caching-pdfs)

 Protecting PDFs with a password
===============================

###  On this page

1. [ Owner password and permissions ](#content-owner-password-and-permissions)
2. [ Supported drivers ](#content-supported-drivers)
3. [ Decrypting a PDF ](#content-decrypting-a-pdf)
4. [ Using a custom encrypter ](#content-using-a-custom-encrypter)

You can password-protect a generated PDF with the `encrypt` method. The PDF is encrypted with AES-256 in pure PHP after it is rendered, so no external binaries (such as `qpdf`) are required. This also works on platforms where you cannot install binaries, like Laravel Cloud.

This feature requires the `tecnickcom/tc-lib-pdf-encrypt` package:

```
composer require tecnickcom/tc-lib-pdf-encrypt
```

Pass a user password to require it before the document can be opened.

```
use Spatie\LaravelPdf\Facades\Pdf;

Pdf::view('pdf.invoice', ['invoice' => $invoice])
    ->encrypt(userPassword: 'open-sesame')
    ->save('/some/directory/invoice.pdf');
```

Owner password and permissions
--------------------------------------------------------------------------------------------------------------------------------------------------

You can also set an owner password and restrict what readers may do with the document. The owner password grants full access (including changing the permissions), while the user password opens the document with the restrictions applied.

Permissions are passed as a list of `Permission` cases. Only the permissions you pass are granted. When you do not pass any permissions, every permission is granted and the password only controls opening the document.

```
use Spatie\LaravelPdf\Enums\Permission;
use Spatie\LaravelPdf\Facades\Pdf;

Pdf::view('pdf.invoice', ['invoice' => $invoice])
    ->encrypt(
        userPassword: 'open-sesame',
        ownerPassword: 'owner-secret',
        permissions: [Permission::Print, Permission::Copy],
    )
    ->save('/some/directory/invoice.pdf');
```

The available permissions are `Print`, `Copy`, `Modify`, `Annotate`, `FillForms`, `Extract`, `Assemble`, and `PrintHighResolution`.

Because the document is encrypted in place rather than rebuilt, links, the document tag tree, and metadata set with `meta` are preserved.

> When you generate a protected PDF on the queue with `saveQueued`, the passwords are stored in the queue payload until the job runs. Make sure your queue storage (database, Redis) is secured accordingly.

Supported drivers
-----------------------------------------------------------------------------------------------------------

Encryption is applied as a post-processing step, so it works with any driver that produces a PDF using a classic cross-reference table. This includes Browsershot, the Chrome driver, and DOMPDF. PDFs that use compressed object streams (which some WeasyPrint output uses) are not supported by the default encrypter, and a `CouldNotEncryptPdf` exception is thrown. In that case you can bind your own encrypter (see below).

Decrypting a PDF
--------------------------------------------------------------------------------------------------------

You can decrypt a protected PDF with the `decrypt` method on the facade. It accepts either a path to a PDF file or the raw PDF contents, together with the user or owner password, and returns the decrypted PDF.

```
use Spatie\LaravelPdf\Facades\Pdf;

// Pass a path...
$decrypted = Pdf::decrypt('/some/directory/invoice.pdf', 'open-sesame');

// ...or the raw contents
$decrypted = Pdf::decrypt($contents, 'open-sesame');
```

When the password is incorrect, a `Spatie\LaravelPdf\Exceptions\CouldNotDecryptPdf` exception is thrown, so you can catch it to handle a wrong password.

```
use Spatie\LaravelPdf\Exceptions\CouldNotDecryptPdf;
use Spatie\LaravelPdf\Facades\Pdf;

try {
    $decrypted = Pdf::decrypt('/some/directory/invoice.pdf', $password);
} catch (CouldNotDecryptPdf $exception) {
    // The password was incorrect, or the PDF could not be decrypted.
}
```

Using a custom encrypter
--------------------------------------------------------------------------------------------------------------------------------

The default encrypter handles AES-256 protection. If you want to use a different strategy (for example a `qpdf` binary or a commercial library), implement the `Spatie\LaravelPdf\Encryption\PdfEncrypter` contract and point the `encrypter` config key to your class.

```
// config/laravel-pdf.php

'encrypter' => App\Pdf\MyEncrypter::class,
```

```
namespace App\Pdf;

use Spatie\LaravelPdf\Encryption\PdfEncrypter;
use Spatie\LaravelPdf\Encryption\PdfEncryption;

class MyEncrypter implements PdfEncrypter
{
    public function encrypt(string $pdf, PdfEncryption $encryption): string
    {
        // return the encrypted PDF
    }

    public function decrypt(string $pdf, string $password): string
    {
        // return the decrypted PDF
    }
}
```

 A good
match?
-------------

### What we do best

- All things Laravel
- Custom frontend components
- Building APIs
- AI-powered features
- Simplifying things
- Clean solutions
- Integrating services

### Not our cup of tea

- WordPress themes
- Cutting corners
- Free mockups to win a job
- "Just execute the briefing"

 In short: we'd like to be a **substantial part** of your project.

 [ Get in touch via email ](mailto:info@spatie.be?subject=A%20good%20match%21&body=Tell%20us%20as%20much%20as%20you%20can%20about%0A-%20your%20online%20project%0A-%20your%20planning%0A-%20your%20budget%0A-%20%E2%80%A6%0A%0AAnything%20that%20helps%20us%20to%20start%20straightforward%21)
