Sign PDF files with valid x509 certificate
Require this package in your composer.json and update composer. This will download the package and the dependencies libraries also.
composer require lsnepomuceno/laravel-a1-pdf-sign
💥
Is your project not Laravel / Lumen?
If you want to use this package in a project that is not based on Laravel / Lumen, you need to make the adjustments below
1 - Install dependencies to work correctly.
composer require illuminate/container illuminate/filesystem ramsey/uuid
2 - Prepare the code to launch the Container and FileSystem instance.
<?php
require_once 'vendor/autoload.php';
use Illuminate\Container\Container;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Facades\Facade;
try {
$app = new Container();
$app->singleton('app', Container::class);
$app->singleton('files', fn () => new Filesystem);
Facade::setFacadeApplication($app);
// Allow the use of Facades, only if necessary
// $app->withFacades();
} catch (\Throwable $th) {
// TODO necessary
}
3 - After this parameterization, your project will work normally.
<?php
require_once 'vendor/autoload.php';
use Illuminate\Container\Container;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Facades\Facade;
use LSNepomuceno\LaravelA1PdfSign\ManageCert;
try {
$app = new Container();
$app->singleton('app', Container::class);
$app->singleton('files', fn () => new Filesystem);
Facade::setFacadeApplication($app);
$cert = new ManageCert;
$cert->fromPfx(path/to/certificate.pfx', 'password');
var_dump($cert->getCert());
} catch (\Throwable $th) {
// TODO necessary
}
Usage
Working with certificate
1 - Reading the certificate from file.
<?php
use LSNepomuceno\LaravelA1PdfSign\ManageCert;
class ExampleController() {
public function dummyFunction(){
try {
$cert = new ManageCert;
$cert->fromPfx('path/to/certificate.pfx', 'password');
dd($cert->getCert());
} catch (\Throwable $th) {
// TODO necessary
}
}
}
2 - Reading the certificate from upload.
<?php
use Illuminate\Http\Request;
use LSNepomuceno\LaravelA1PdfSign\ManageCert;
class ExampleController() {
public function dummyFunction(Request $request){
try {
$cert = new ManageCert;
$cert->fromUpload($request->pfxUploadedFile, $request->password);
dd($cert->getCert());
} catch (\Throwable $th) {
// TODO necessary
}
}
}
3 - The expected result will be as shown below.
4 - Store certificate data securely in the database.
IMPORTANT: Store certificate column as binary data type
<?php
use App\Models\Certificate;
use LSNepomuceno\LaravelA1PdfSign\ManageCert;
class ExampleController() {
public function dummyFunction(){
try {
$cert = new ManageCert;
$cert->fromPfx('path/to/certificate.pfx', 'password');
} catch (\Throwable $th) {
// TODO necessary
}
// Postgres or MS SQL Server
Certificate::create([
'certificate' => $cert->getEncrypter()->encryptString($cert->getCert()->original)
'password' => $cert->getEncrypter()->encryptString('password'),
'hash' => $cert->getHashKey(), // IMPORTANT
...
]);
// For MySQL
Certificate::create([
'certificate' => $cert->encryptBase64BlobString($cert->getCert()->original)
'password' => $cert->getEncrypter()->encryptString('password'),
'hash' => $cert->getHashKey(), // IMPORTANT
...
]);
}
}
5 - Reading certificate from database.
<?php
use LSNepomuceno\LaravelA1PdfSign\ManageCert;
use Illuminate\Support\{Str, Facades\File};
class CertificateModel() {
public function parse() {
$cert = new ManageCert;
$cert->setHashKey($this->hash);
$pfxName = $cert->getTempDir() . Str::orderedUuid() . '.pfx';
// Postgres or MS SQL Server
File::put($pfxName, $cert->getEncrypter()->decryptString($this->bb_cert));
// For MySQL
File::put($pfxName, $cert->decryptBase64BlobString($this->bb_cert));
try {
return $cert->fromPfx(
$pfxName,
$cert->getEncrypter()->decryptString($this->password)
);
} catch (\Throwable $th) {
// TODO necessary
}
}
}
Sign PDF File
1 - Sign PDF with certificate from file or upload.
<?php
use Illuminate\Http\Request;
use LSNepomuceno\LaravelA1PdfSign\{ManageCert, SignaturePdf};
class ExampleController() {
public function dummyFunction(Request $request){
// FROM FILE
try {
$cert = new ManageCert;
$cert->fromPfx('path/to/certificate.pfx', 'password');
} catch (\Throwable $th) {
// TODO necessary
}
// FROM UPLOAD
try {
$cert = new ManageCert;
$cert->fromUpload($request->pfxUploadedFile, $request->password);
dd($cert->getCert());
} catch (\Throwable $th) {
// TODO necessary
}
// Returning signed resource string
try {
$pdf = new SignaturePdf('path/to/pdf/file.pdf', $cert->getCert(), SignaturePdf::MODE_RESOURCE) // Resource mode is default
$resource = $pdf->signature();
// TODO necessary
} catch (\Throwable $th) {
// TODO necessary
}
// Downloading signed file
try {
$pdf = new SignaturePdf('path/to/pdf/file.pdf', $cert->getCert(), SignaturePdf::MODE_DOWNLOAD)
return $pdf->signature(); // The file will be downloaded
} catch (\Throwable $th) {
// TODO necessary
}
}
}
2 - Sign PDF with certificate from database (model based).
<?php
use Illuminate\Http\Request;
use App\Models\Certificate;
use LSNepomuceno\LaravelA1PdfSign\{ManageCert, SignaturePdf};
class ExampleController() {
public function dummyFunction(Request $request){
// Find certificate
$cert = Certificate::find(1);
// Returning signed resource string
try {
$pdf = new SignaturePdf('path/to/pdf/file.pdf', $cert->parse(), SignaturePdf::MODE_RESOURCE) // Resource mode is default
$resource = $pdf->signature();
// TODO necessary
} catch (\Throwable $th) {
// TODO necessary
}
// Downloading signed file
try {
$pdf = new SignaturePdf('path/to/pdf/file.pdf', $cert->parse(), SignaturePdf::MODE_DOWNLOAD)
return $pdf->signature(); // The file will be downloaded
} catch (\Throwable $th) {
// TODO necessary
}
}
}
3 - The expected result in Adobe Acrobat/Reader will be as shown below.
Tests
Run the tests with:
composer run-script test
or
vendor/bin/phpunit