spomky-labs/pki-framework
PHP 8.1+ framework for PKI: X.509 certificates, ASN.1 (X.690 DER) encoding/decoding, X.501/X.520 DN parsing, PEM (RFC 7468) support, and cryptographic/PKCS-related ASN.1 types. mbstring required; gmp/bcmath recommended.
Installation:
composer require spomky-labs/pki-framework
Ensure your composer.json meets the requirements (PHP ≥8.1, mbstring, and optionally gmp/bcmath).
First Use Case: Parse an existing X.509 certificate from a PEM file:
use SpomkyLabs\PkiFramework\Certificate;
$certificate = Certificate::fromFile('path/to/certificate.pem');
$subject = $certificate->getSubject();
$notBefore = $certificate->getValidity()->getNotBefore();
Key Classes to Explore:
Certificate: Core class for X.509 certificates.CertificateFactory: Generate new certificates.CertificateRevocationList: Handle CRLs.Asn1: Work with ASN.1 structures directly.Pem: Encode/decode PEM formats.Where to Look First:
$cert = Certificate::fromFile('cert.pem');
// or from DER
$cert = Certificate::fromDER(file_get_contents('cert.der'));
$caCert = Certificate::fromFile('ca.pem');
$cert->validate($caCert);
if ($cert->isValid()) {
// Certificate is valid
}
use SpomkyLabs\PkiFramework\CertificateFactory;
$factory = new CertificateFactory();
$cert = $factory->createSelfSigned(
'CN=My CA',
'CN=My Server',
'sha256WithRSAEncryption',
365
);
$caCert = Certificate::fromFile('ca.pem');
$caKey = PrivateKey::fromFile('ca.key');
$cert = $factory->createSigned(
$caCert,
$caKey,
'CN=My Server',
'sha256WithRSAEncryption',
365
);
$pem = $cert->toPem();
$der = $cert->toDER();
$cert = Certificate::fromPem($pemString);
use SpomkyLabs\PkiFramework\CertificateRevocationList;
$crl = new CertificateRevocationList();
$crl->addRevokedCertificate($revokedCert, new \DateTime('now'));
$crl->sign($caCert, $caKey);
$crl = CertificateRevocationList::fromFile('crl.pem');
$cert->validate($crl);
use SpomkyLabs\PkiFramework\Asn1;
$asn1 = Asn1::fromDER($derData);
$der = $asn1->toDER();
$certData = $cert->toDER();
$model->certificate_data = $certData;
$model->save();
public function handle(Request $request, Closure $next) {
$clientCert = $request->getCertificate(); // Assuming you extract the cert
$caCert = Certificate::fromFile(storage_path('ca.pem'));
$clientCert->validate($caCert);
return $next($request);
}
// Customize token validation to check certificate SANs
Passport::tokensCan([
'certificate-bound-token' => function ($user, $token) {
$cert = $token->getCertificate(); // Hypothetical; adapt to your needs
return $cert->getSubjectAlternativeNames()->contains('email:user@example.com');
}
]);
$extension = new Extension(
new ObjectIdentifier('1.2.3.4'), // Your custom OID
false, // Critical
$asn1Data // Your ASN.1 data
);
$cert->addExtension($extension);
$extensions = $cert->getExtensions();
foreach ($extensions as $extension) {
if ($extension->getOid()->equals('1.2.3.4')) {
// Handle custom extension
}
}
use Illuminate\Support\Facades\Storage;
Storage::put('private/ca.key', $caKey->toPem());
$cacheKey = 'cert_' . md5($certPath);
$cert = Cache::remember($cacheKey, now()->addHours(1), function () use ($certPath) {
return Certificate::fromFile($certPath);
});
try {
$cert->validate($caCert);
} catch (CertificateException $e) {
Log::error('Certificate validation failed: ' . $e->getMessage());
abort(403, 'Invalid certificate');
}
public function testCertificateValidation() {
$caCert = Certificate::fromFile('tests/fixtures/ca.pem');
$validCert = Certificate::fromFile('tests/fixtures/valid.pem');
$invalidCert = Certificate::fromFile('tests/fixtures/invalid.pem');
$this->assertTrue($validCert->validate($caCert));
$this->assertFalse($invalidCert->validate($caCert));
}
Log::info('Issued certificate', [
'subject' => $cert->getSubject()->getName(),
'serial' => $cert->getSerialNumber(),
]);
$caCerts = collect([
Certificate::fromFile('ca1.pem'),
Certificate::fromFile('ca2.pem'),
]);
gmp or bcmath for large-key operations to improve performance..gitignore and Laravel’s environment-based storage (e.g., storage/app/private).config/filesystems.php to restrict access to sensitive files.$cert->validate($caCert);
$cert->isValid(); // Checks expiration
$validator = new CertificateValidator();
$validator->setCaCert($caCert);
$validator->setCheckRevocation
How can I help you explore Laravel packages today?