Skip to content

Commit

Permalink
Merge pull request #3 from exonet/release-v0.0.1
Browse files Browse the repository at this point in the history
Release v0.0.1
  • Loading branch information
styxit authored Jan 30, 2019
2 parents a0db8c7 + 75306b0 commit 109232d
Show file tree
Hide file tree
Showing 16 changed files with 649 additions and 1 deletion.
10 changes: 10 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
max_line_length = 120
trim_trailing_whitespace = true
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.idea
/vendor/
composer.lock
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Changelog
All notable changes to `SSL converter` will be documented in this file.

Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) principles.

## Unreleased
[Compare v0.0.1 - Unreleased](https://github.com/exonet/ssl-converter/compare/v0.0.1...develop)

## [v0.0.1](https://github.com/exonet/ssl-converter/releases/tag/v0.0.1) - 2019-01-30
### Added
- Initial release.
53 changes: 52 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,53 @@
# ssl-converter
# SSL converter
PHP package to convert an SSL certificate to various formats (e.g PKC12, PEM).

## Install
Via Composer

``` bash
$ composer require exonet/ssl-converter
```

## Example usage
The example below shows how combine separate contents of a certificate to a combined PEM string.
- `crt` The certificate (typically the contents of `.crt` file).
- `key` The private key (typically the contents of the `.key` file)
- `ca bundle` The certificate of the intermediate and/or the trusted root certificate

```php
// Initialise a new SSL converter.
$converter = new Converter();

// Setup the plain format class that should be converter.
$plain = new Plain();
$plain
->setKey('-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
')
->setCrt('-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
')
->setCaBundle('-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
');

// Convert the plain certificate.
$pem = $converter
->from($plain)
->to(new Pem());

// Save as zip file:
$pem->asZip('./');

// Get an array with the certificate files:
print_r($pem->asFiles());

// Get the certificate as string:
print_r($pem->asString());
```

## Change log
Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
25 changes: 25 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "exonet/ssl-converter",
"description": "PHP package to convert an SSL certificate to various formats (e.g PKC12, PEM).",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Exonet B.V.",
"email": "[email protected]"
}
],
"require": {
"php": "~7.1",
"ext-openssl": "*",
"ext-zip": "*"
},
"autoload": {
"psr-4": {
"Exonet\\SslConverter\\": "src"
}
},
"config": {
"sort-packages": true
}
}
143 changes: 143 additions & 0 deletions src/Converter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
<?php

namespace Exonet\SslConverter;

use Exonet\SslConverter\Exceptions\ZipException;
use Exonet\SslConverter\Formats\FormatInterface;
use ZipArchive;

class Converter
{
/**
* @var FormatInterface The input format to be converted.
*/
protected $to;

/**
* @var FormatInterface The output format to convert to.
*/
protected $from;

/**
* @var string The certificate name.
*/
protected $certificateName = 'certificate';

/**
* Set the name of the certificate.
*
* @param string $certificateName The certificate.
*
* @return $this The current Converter instance.
*/
public function setName(string $certificateName) : self
{
$this->certificateName = $certificateName;

return $this;
}

/**
* Set the format that should be converted.
*
* @param FormatInterface $from The input format to be converted.
*
* @return $this Instance of this class.
*/
public function from(FormatInterface $from) : self
{
$this->from = $from;

return $this;
}

/**
* Set the format that should be converted to.
*
* @param FormatInterface $to The output format to convert to.
*
* @return $this Instance of this class
*/
public function to(FormatInterface $to) : self
{
$this->to = $to;

return $this;
}

/**
* Convert the input format to the provided output format as a string.
*
* @return string The converted format as a string that can be saved to a file.
*
* @throws Exceptions\InvalidResource When the provided certificate is invalid.
* @throws Exceptions\MissingRequiredInformation When some required certificate data is missing.
*/
public function asString() : string
{
return $this->to
->setName($this->certificateName)
->setPlain($this->from->getPlain())
->toString();
}

/**
* Convert the input format to the provided output format as an array of files. The array key is the file name, the
* array value the file contents.
*
* @return string[] The converted format as an array of files that can be saved to a file.
*
* @throws Exceptions\InvalidResource When the provided certificate is invalid.
* @throws Exceptions\MissingRequiredInformation When some required certificate data is missing.
*/
public function asFiles() : array
{
return $this->to
->setName($this->certificateName)
->setPlain($this->from->getPlain())
->export();
}

/**
* Convert the input format to the provided output format and save the file (or files) as zip.
*
* @param string $path The path where to store the zip file.
*
* @return bool True when the zip is created and stored.
*
* @throws Exceptions\InvalidResource When the provided certificate is invalid.
* @throws Exceptions\MissingRequiredInformation When some required certificate data is missing.
* @throws ZipException When the files can not be zipped.
*/
public function asZip(string $path) : bool
{
$filename = sprintf('%s/%s.zip', rtrim($path, '/'), $this->certificateName);

if (!is_dir($path) || !is_writable($path)) {
throw new ZipException(sprintf('The directory [%s] is does not exists or is not writable.', $path));
}

if (is_file($filename) && !is_writable($filename)) {
throw new ZipException(sprintf('The file [%s] already exists and is not writable.', $filename));
}

$files = $this->to
->setName($this->certificateName)
->setPlain($this->from->getPlain())
->export();

$zip = new ZipArchive();
$zip->open($filename, ZipArchive::CREATE);
foreach ($files as $name => $content) {
$zip->addFromString($name, $content);
}

if ($zip->status !== 0) {
throw new ZipException($zip->getStatusString());
}

$zip->close();

return file_exists($filename);
}
}
7 changes: 7 additions & 0 deletions src/Exceptions/InvalidResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Exonet\SslConverter\Exceptions;

class InvalidResource extends SslConverterException
{
}
7 changes: 7 additions & 0 deletions src/Exceptions/MissingRequiredInformation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Exonet\SslConverter\Exceptions;

class MissingRequiredInformation extends SslConverterException
{
}
7 changes: 7 additions & 0 deletions src/Exceptions/NotImplementedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Exonet\SslConverter\Exceptions;

class NotImplementedException extends SslConverterException
{
}
9 changes: 9 additions & 0 deletions src/Exceptions/SslConverterException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace Exonet\SslConverter\Exceptions;

use Exception;

class SslConverterException extends Exception
{
}
7 changes: 7 additions & 0 deletions src/Exceptions/ZipException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Exonet\SslConverter\Exceptions;

class ZipException extends SslConverterException
{
}
89 changes: 89 additions & 0 deletions src/Formats/AbstractFormat.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

namespace Exonet\SslConverter\Formats;

use Exonet\SslConverter\Exceptions\NotImplementedException;

abstract class AbstractFormat implements FormatInterface
{
/**
* @var Plain The plain certificate required for exporting.
*/
protected $plainCertificate;

/**
* @var mixed[] List with options for the format.
*/
protected $options = [];

/**
* @var string The certificate name.
*/
protected $name = 'certificate';

/**
* AbstractFormat constructor.
*
* @param mixed[] $options The (optional) array with options for this format.
*/
public function __construct(array $options = [])
{
$this->setOptions($options);
}

/**
* {@inheritdoc}
*/
public function setName(string $name) : FormatInterface
{
$this->name = $name;

return $this;
}

/**
* {@inheritdoc}
*/
public function getName() : string
{
return $this->name;
}

/**
* {@inheritdoc}
*/
public function setPlain(Plain $plain) : FormatInterface
{
$this->plainCertificate = $plain;

return $this;
}

/**
* {@inheritdoc}
*/
public function setOptions(array $options) : FormatInterface
{
$this->options = $options;

return $this;
}

/**
* {@inheritdoc}
*/
public function getOptions() : array
{
return $this->options;
}

/**
* @inheritdoc
*
* @throws NotImplementedException When this method is not implemented.
*/
public function getPlain() : Plain
{
throw new NotImplementedException('The [getPlain] method is not implemented for this format.');
}
}
Loading

0 comments on commit 109232d

Please sign in to comment.