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

Pki Framework Laravel Package

spomky-labs/pki-framework

PHP 8.1+ framework for Public Key Infrastructure: X.509 certificates (incl. attribute certs), ASN.1 DER encoding/decoding, X.501/X.520 DN parsing, PEM (RFC 7468) handling, and PKCS-oriented cryptography utilities.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to First Use

  1. Install the Package

    composer require spomky-labs/pki-framework
    

    Ensure gmp or bcmath extensions are enabled for cryptographic operations.

  2. Load a Certificate (PEM or DER)

    use SpomkyLabs\PkiFramework\Certificate;
    
    $certificate = Certificate::loadFromFile('path/to/certificate.pem');
    // or
    $certificate = Certificate::loadFromString($pemContent);
    
  3. Inspect Certificate Details

    echo $certificate->getSubject()->getCommonName(); // Subject CN
    echo $certificate->getIssuer()->getOrganization(); // Issuer O
    echo $certificate->getValidity()->getNotBefore()->format('Y-m-d'); // Validity
    
  4. Validate a Certificate

    $isValid = $certificate->isValid();
    $errors = $certificate->getValidationErrors();
    
  5. Generate a Self-Signed Certificate (Quick Test)

    use SpomkyLabs\PkiFramework\Certificate\CertificateGenerator;
    
    $generator = new CertificateGenerator();
    $certificate = $generator
        ->withSubject(new Subject('CN=Test Certificate'))
        ->withValidity(new Validity(new DateTime(), new DateTime('+1 year')))
        ->withPublicKey($publicKey) // Load from key pair
        ->generate();
    

First Use Case: Validate Incoming Request Certificates

use SpomkyLabs\PkiFramework\Certificate;

public function validateClientCertificate(Request $request)
{
    $clientCert = $request->getClientCert();
    $cert = Certificate::loadFromString($clientCert);

    if (!$cert->isValid()) {
        throw new \RuntimeException('Invalid certificate: ' . implode(', ', $cert->getValidationErrors()));
    }

    // Check custom logic (e.g., SANs, issuer, or extensions)
    if (!$cert->getSubject()->getCommonName()->equals('Allowed Service')) {
        throw new \RuntimeException('Certificate not authorized');
    }

    return response()->json(['status' => 'valid']);
}

Implementation Patterns

Core Workflows

1. Certificate Issuance (Private CA)

use SpomkyLabs\PkiFramework\Certificate\CertificateGenerator;
use SpomkyLabs\PkiFramework\Certificate\Extension\SubjectAlternativeName;
use SpomkyLabs\PkiFramework\Certificate\Extension\KeyUsage;

public function issueCertificate(string $subjectCN, array $sans = []): string
{
    $generator = new CertificateGenerator();

    // Configure subject and validity
    $generator->withSubject(new Subject("CN=$subjectCN"));
    $generator->withValidity(new Validity(
        new DateTime(),
        new DateTime('+1 year')
    ));

    // Add SANs (e.g., for DNS or IP validation)
    if (!empty($sans)) {
        $generator->withExtension(new SubjectAlternativeName($sans));
    }

    // Key usage (e.g., digital signature, key encipherment)
    $generator->withExtension(new KeyUsage([
        KeyUsage::DIGITAL_SIGNATURE,
        KeyUsage::KEY_ENCIPHERMENT
    ]));

    // Generate key pair (RSA 2048-bit)
    $keyPair = KeyPair::generate(2048);

    // Sign with CA private key (loaded from secure storage)
    $caPrivateKey = PrivateKey::loadFromFile('/path/to/ca_private.key');
    $generator->withPrivateKey($caPrivateKey);

    $certificate = $generator->generate();

    return $certificate->toPEM();
}

2. Certificate Revocation (CRL)

use SpomkyLabs\PkiFramework\Crl\CrlGenerator;

public function generateCrl(): string
{
    $crlGenerator = new CrlGenerator();

    // Add revoked certificates (serial number => revocation date)
    $crlGenerator->addRevokedCertificate(
        new RevokedCertificate(
            new SerialNumber('1234567890'), // Serial from issued cert
            new DateTime('2023-01-01')     // Revocation date
        )
    );

    // Sign with CA private key
    $caPrivateKey = PrivateKey::loadFromFile('/path/to/ca_private.key');
    $crlGenerator->withPrivateKey($caPrivateKey);

    $crl = $crlGenerator->generate();

    return $crl->toPEM();
}

3. OCSP Response Generation

use SpomkyLabs\PkiFramework\Ocsp\OcspResponseGenerator;

public function generateOcspResponse(string $certSerial): string
{
    $ocspGenerator = new OcspResponseGenerator();

    // Configure response status
    $ocspGenerator->addSingleResponse(
        new SingleResponse(
            new SerialNumber($certSerial),
            ResponseStatus::GOOD, // or GOOD, REVOKED, UNKNOWN
            new DateTime(),        // ThisUpdate
            new DateTime('+1 day') // NextUpdate
        )
    );

    // Sign with CA private key
    $caPrivateKey = PrivateKey::loadFromFile('/path/to/ca_private.key');
    $ocspGenerator->withPrivateKey($caPrivateKey);

    $ocspResponse = $ocspGenerator->generate();

    return $ocspResponse->toPEM();
}

4. Certificate Chain Validation

use SpomkyLabs\PkiFramework\Certificate\CertificateChainValidator;

public function validateCertificateChain(array $certificates): bool
{
    $validator = new CertificateChainValidator();

    // Load trusted root CA
    $rootCa = Certificate::loadFromFile('/path/to/root_ca.pem');
    $validator->withTrustedCertificates([$rootCa]);

    // Validate chain
    $chain = [];
    foreach ($certificates as $cert) {
        $chain[] = Certificate::loadFromString($cert);
    }

    $result = $validator->validate($chain);

    return $result->isValid();
}

Integration Tips

Laravel Service Provider Setup

// app/Providers/PkiServiceProvider.php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use SpomkyLabs\PkiFramework\Certificate;
use SpomkyLabs\PkiFramework\Certificate\CertificateChainValidator;

class PkiServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->singleton(CertificateChainValidator::class, function ($app) {
            $validator = new CertificateChainValidator();

            // Load trusted CAs from config
            $trustedCAs = config('pki.trusted_cas');
            foreach ($trustedCAs as $caPath) {
                $validator->withTrustedCertificates([
                    Certificate::loadFromFile($caPath)
                ]);
            }

            return $validator;
        });
    }
}

Middleware for Certificate Validation

// app/Http/Middleware/ValidateClientCertificate.php
namespace App\Http\Middleware;

use Closure;
use SpomkyLabs\PkiFramework\Certificate;
use Illuminate\Http\Request;

class ValidateClientCertificate
{
    public function handle(Request $request, Closure $next)
    {
        if ($request->hasHeader('ssl-client-cert')) {
            $clientCert = $request->header('ssl-client-cert');
            $cert = Certificate::loadFromString($clientCert);

            if (!$cert->isValid()) {
                abort(403, 'Invalid client certificate');
            }

            // Attach certificate to request for downstream use
            $request->merge(['client_certificate' => $cert]);
        }

        return $next($request);
    }
}

Artisan Command for Certificate Management

// app/Console/Commands/IssueCertificate.php
namespace App\Console\Commands;

use Illuminate\Console\Command;
use SpomkyLabs\PkiFramework\Certificate\CertificateGenerator;

class IssueCertificate extends Command
{
    protected $signature = 'pki:issue
        {--subject= : Subject CN}
        {--sans= : Comma-separated SANs (e.g., DNS:example.com,IP:192.168.1.1)}
        {--output= : Output file path}';

    protected $description = 'Issue a new certificate';

    public function handle()
    {
        $generator = new CertificateGenerator();
        $generator->withSubject(new Subject("CN={$this->option('subject')}"));

        if ($sans = $this->option('sans')) {
            $generator->withExtension(new SubjectAlternativeName(explode(',', $sans)));
        }

        $keyPair = KeyPair::generate(2048);
        $generator->withPublicKey($keyPair->getPublicKey());

        // Load CA private key from secure storage
        $caPrivateKey = PrivateKey::loadFromFile(config('pki.ca_private_key_path'));
        $generator->withPrivateKey($caPrivateKey);

        $certificate = $generator->generate();

        if ($output = $this->option('output
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.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata