caiquemcz / ssl-converter
SSL certificate converter (PEM/DER/PKCS12), CA bundle and private keys in PHP.
Installs: 5
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/caiquemcz/ssl-converter
Requires
- php: >=7.4
Requires (Dev)
- phpunit/phpunit: ^9.6
- squizlabs/php_codesniffer: ^4.0
README
A PHP library for converting SSL certificates between different formats (PEM, PFX/PKCS12, JKS), including CA bundles and private keys.
Features
- Convert certificates to PEM format with full chain
- Convert certificates to PFX/PKCS12 format
- Convert certificates to JKS (Java KeyStore) format
- Support for encrypted private keys
- CA bundle handling
- Legacy algorithm support for older systems
- Clean, SOLID architecture
- Fully tested with PHPUnit
Requirements
- PHP >= 7.4
- OpenSSL extension
- Symfony Process component
- Java keytool (for JKS conversion)
Installation
composer require caiquemcz/ssl-converter
Usage
Quick Start with Fluent API (Recommended)
The simplest way to convert certificates is using the fluent SslConverter
API:
use CaiqueMcz\SslConverter\SslConverter; // Convert to PEM $response = (new SslConverter($certificate)) ->withCaBundle($caBundle) ->withPrivateKey($privateKey, $password) // password is optional ->toPem(); // Convert to PFX $response = (new SslConverter($certificate)) ->withCaBundle($caBundle) // optional ->withPrivateKey($privateKey, $password) // password is optional ->toPfx('pfx-password', $useLegacy); // useLegacy is optional (default: false) // Convert to JKS $response = (new SslConverter($certificate)) ->withCaBundle($caBundle) // optional ->withPrivateKey($privateKey, $password) // password is optional ->toJks('jks-password', 'alias', $useLegacy); // alias and useLegacy are optional // Save the converted file file_put_contents( $response->virtualFile()->getName(), $response->virtualFile()->getContent() );
Real-World Examples
Example 1: Convert PEM to PFX for Windows servers
use CaiqueMcz\SslConverter\SslConverter; $certificate = file_get_contents('certificate.pem'); $privateKey = file_get_contents('private.key'); $caBundle = file_get_contents('ca-bundle.pem'); $response = (new SslConverter($certificate)) ->withCaBundle($caBundle) ->withPrivateKey($privateKey) ->toPfx('SecurePassword123!'); file_put_contents('certificate.pfx', $response->virtualFile()->getContent());
Example 2: Convert to JKS for Java applications
use CaiqueMcz\SslConverter\SslConverter; $certificate = file_get_contents('certificate.crt'); $privateKey = file_get_contents('private.key'); $response = (new SslConverter($certificate)) ->withPrivateKey($privateKey) ->toJks('keystore-password', 'myapp'); file_put_contents('keystore.jks', $response->virtualFile()->getContent());
Example 3: Handle encrypted private keys
use CaiqueMcz\SslConverter\SslConverter; $certificate = file_get_contents('certificate.pem'); $encryptedKey = file_get_contents('encrypted-private.key'); $response = (new SslConverter($certificate)) ->withPrivateKey($encryptedKey, 'key-encryption-password') ->toPfx('pfx-password'); file_put_contents('certificate.pfx', $response->virtualFile()->getContent());
Example 4: Use legacy algorithm for older systems
use CaiqueMcz\SslConverter\SslConverter; $certificate = file_get_contents('certificate.pem'); $privateKey = file_get_contents('private.key'); $response = (new SslConverter($certificate)) ->withPrivateKey($privateKey) ->toPfx('password', true); // true = use legacy algorithm file_put_contents('certificate.pfx', $response->virtualFile()->getContent());
Advanced Usage with Converters
For more control, use the converter classes directly:
Converting to PEM Format
use CaiqueMcz\SslConverter\Converter; use CaiqueMcz\SslConverter\Formats\PemFormat; use CaiqueMcz\SslConverter\ValueObjects\CertificateData; use CaiqueMcz\SslConverter\ValueObjects\PrivateKeyData; $certificateData = new CertificateData( $certificate, new PrivateKeyData($privateKey, $privateKeyPassword), $caBundle ); $pemFormat = new PemFormat($certificateData); $converter = new Converter(); $response = $converter->convert($pemFormat); // Get the main file (fullchain.pem) $mainFile = $response->virtualFile(); echo $mainFile->getName(); // fullchain.pem echo $mainFile->getContent(); // Certificate content // Get extra files (ca-bundle.pem, private.pem) foreach ($response->extraVirtualFile() as $file) { echo $file->getName(); echo $file->getContent(); }
Converting to PFX Format
use CaiqueMcz\SslConverter\Formats\PfxFormat; $certificateData = new CertificateData( $certificate, new PrivateKeyData($privateKey), $caBundle ); $pfxFormat = new PfxFormat($certificateData); $pfxFormat->setPfxPassword('your-password'); // Optional: Use legacy algorithm for older systems $pfxFormat->withLegacyAlgorithm(); $converter = new Converter(); $response = $converter->convert($pfxFormat); $pfxFile = $response->virtualFile(); file_put_contents('certificate.pfx', $pfxFile->getContent());
Converting to JKS Format
use CaiqueMcz\SslConverter\Formats\JksFormat; $certificateData = new CertificateData( $certificate, new PrivateKeyData($privateKey), $caBundle ); $jksFormat = new JksFormat($certificateData); $jksFormat->setJksPassword('your-password'); // Optional: Use legacy algorithm $jksFormat->withLegacyAlgorithm(); $converter = new Converter(); $response = $converter->convert($jksFormat); $jksFile = $response->virtualFile(); file_put_contents('certificate.jks', $jksFile->getContent());
Working with Encrypted Private Keys
use CaiqueMcz\SslConverter\ValueObjects\PrivateKeyData; // Private key with password $privateKeyData = new PrivateKeyData($privateKey, 'key-password'); $certificateData = new CertificateData( $certificate, $privateKeyData, $caBundle ); // Use as normal $pfxFormat = new PfxFormat($certificateData); $pfxFormat->setPfxPassword('pfx-password');
Getting All Files
$response = $converter->convert($format); // Get all files including main and extras $allFiles = $response->getAllVirtualFiles(); foreach ($allFiles->get() as $file) { echo sprintf( "File: %s (Size: %d bytes)\n", $file->getName(), $file->getSize() ); file_put_contents($file->getName(), $file->getContent()); }
Format Support
PEM Format
- Generates
fullchain.pem
(certificate + CA bundle) - Optional
ca-bundle.pem
(CA certificates) - Optional
private.pem
(private key) - Requires CA bundle
PFX/PKCS12 Format
- Generates
certificate.pfx
- Requires private key
- Requires password
- Supports legacy algorithm for compatibility
- Optional CA bundle
JKS Format
- Generates
certificate.jks
- Requires private key
- Requires password
- Requires Java keytool installed
- Supports legacy algorithm
- Optional CA bundle
- Custom alias support
Architecture
The library follows SOLID principles with a clean architecture:
- Value Objects: Immutable data containers (
CertificateData
,PrivateKeyData
,VirtualFile
) - Formats: Strategy pattern for different certificate formats
- Generators: Factory pattern for complex file generation
- Converters: Facade for simple API
- Collections: Type-safe collections for virtual files
Testing
# Run tests composer test # Run tests with coverage composer test-coverage # Code style check composer lint # Fix code style composer lint-fix
Error Handling
All conversion errors throw ConversionException
:
use CaiqueMcz\SslConverter\Exceptions\ConversionException; try { $response = $converter->convert($format); } catch (ConversionException $e) { echo "Conversion failed: " . $e->getMessage(); }
License
MIT License. See LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Credits
Developed by Caique
Support
If you encounter any issues or have questions, please open an issue on GitHub.